在Go语言中,有一些推荐的目录和代码规范,这些规范有助于保持代码的一致性、可读性和可维护性。
项目根目录:
cmd/
:包含应用程序的主包,每个子目录对应一个可执行文件。pkg/
:包含可重用的库代码,这些代码可以被其他项目导入。internal/
:包含私有的应用程序和库代码,这些代码只能在该模块内使用。api/
:包含API定义和协议文件(如Protobuf、GraphQL等)。web/
:包含前端代码(如HTML、CSS、JavaScript等)。configs/
:包含配置文件模板或默认配置。scripts/
:包含构建、安装、分析等脚本。build/
:包含打包和持续集成相关的文件和脚本。docs/
:包含项目的文档。test/
:包含外部测试应用程序和测试数据。示例目录结构:
myproject/ ├── cmd/ │ └── myapp/ │ └── main.go ├── pkg/ │ └── mylib/ │ └── mylib.go ├── internal/ │ └── myinternal/ │ └── myinternal.go ├── api/ ├── web/ ├── configs/ ├── scripts/ ├── build/ ├── docs/ ├── test/ └── go.mod
在 Go 语言中,文件命名遵循简单的约定,主要是为了保持代码的清晰和一致性。以下是一些常见的指导原则:
my_example.go
。my-example.go
。这种命名方式在某些项目中可能会遇到,但在 Go 社区中,下划线更为普遍。file_windows.go
,而针对测试的文件通常以 _test.go
结尾,如 example_test.go
。map.go
或 func.go
。MAX_BUFFER_SIZE
)。gofmt
工具格式化代码。//
进行单行注释,使用/* ... */
进行多行注释。导出的包、函数、类型和变量应有注释。error
类型处理错误,尽量避免使用panic
。_test.go
结尾,并放在与被测试代码相同的包中。package main import ( "errors" "fmt" ) // User represents a user in the system type User struct { ID int Name string Email string } // NewUser creates a new user func NewUser(id int, name, email string) (*User, error) { if id <= 0 { return nil, errors.New("invalid ID") } if name == "" { return nil, errors.New("name cannot be empty") } if email == "" { return nil, errors.New("email cannot be empty") } return &User{ID: id, Name: name, Email: email}, nil } func main() { user, err := NewUser(1, "John Doe", "john@example.com") if err != nil { fmt.Println("Error:", err) return } fmt.Printf("User: %+v\\n", user) }
er
结尾,例如Reader
、Writer
、Closer
等。io.Reader
和io.Writer
接口。io.ReadWriter
接口组合了io.Reader
和io.Writer
接口。nil
,在使用接口时要注意检查接口是否为nil
。package main import ( "fmt" "io" ) // Reader 是一个读取数据的接口 type Reader interface { Read(p []byte) (n int, err error) } // Writer 是一个写入数据的接口 type Writer interface { Write(p []byte) (n int, err error) } // ReadWriter 是一个组合接口,包含 Reader 和 Writer type ReadWriter interface { Reader Writer } // MyReadWriter 是一个实现了 ReadWriter 接口的类型 type MyReadWriter struct{} func (rw *MyReadWriter) Read(p []byte) (n int, err error) { copy(p, "hello") return 5, nil } func (rw *MyReadWriter) Write(p []byte) (n int, err error) { fmt.Println(string(p)) return len(p), nil } func main() { var rw ReadWriter = &MyReadWriter{} buf := make([]byte, 10) rw.Read(buf) rw.Write(buf) }
log
包或第三方日志库(如logrus
、zap
)来记录日志。DEBUG
、INFO
、WARN
、ERROR
、FATAL
。WARN
及以上级别的日志。使用标准库log
包:
package main import ( "log" "os" ) func main() { // 创建一个日志文件 file, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { log.Fatal(err) } defer file.Close() // 设置日志输出到文件 log.SetOutput(file) // 设置日志前缀和标志 log.SetPrefix("INFO: ") log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) // 记录日志 log.Println("This is an info message") log.Println("This is another info message") }
使用第三方日志库logrus
:
package main import ( "github.com/sirupsen/logrus" "os" ) func main() { // 创建一个新的日志实例 logger := logrus.New() // 设置日志输出到文件 file, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { logger.Fatal(err) } defer file.Close() logger.SetOutput(file) // 设置日志格式为JSON格式 logger.SetFormatter(&logrus.JSONFormatter{}) // 设置日志级别 logger.SetLevel(logrus.InfoLevel) // 记录日志 logger.Info("This is an info message") logger.Warn("This is a warning message") logger.Error("This is an error message") }
通过遵循这些规范,希望可以帮助你编写出更清晰、可维护的Go代码。
上一篇:ComfyUI 和 WebUI
下一篇:【Docker学习记录】