# Golang ## Get Started ### Enable dependency tracking 当代码对其他module中包含的package进行了import时,在自己的module中来管理依赖。 自己的module通过`go.mod`文件来定义,`go.mod`文件中会track项目所需要的依赖。 #### go mod init `go mod init `命令会创建一个`go.mod`文件,其中``会是module path。 在实际开发中,module name通常是source code被保存的repository location,例如,`uuid`module的module name为`github.com/google/uuid`。 #### go mod tidy `go mod tidy`命令会根据import添加缺失的module并且移除未使用的module。 ## multi-module workspace 示例目录结构如下所示: - workspace - workspace/hello - workspace/example/hello ### go work init 在本示例中,为了创建多module的workspace,可以执行`go work init ./hello`,其会创建`go.work`文件,并将`./hello`目录下的module包含到`go.work`文件中。 `go.work`内容如下: ``` go 1.18 use ./hello ``` ### go work use 通过`go work use ./example/hello`命令,会将`./example/hello`中的module加入到`go.work`文件中。 `go.work`内容如下: ``` go 1.18 use ( ./hello ./example/hello ) ``` `go work use [-r] [dir]`命令行为如下: - 如果指定目录存在,会为`dir`向`go.work`文件中添加一条use指令 - 如果指定目录不存在,会删除`go.work`文件中关于目录的use指令 ## Gin框架构建restful api 在构建resultful api时,通常都会通过json格式来传递数据,首先,可定义业务实体: ```go // album represents data about a record album. type album struct { ID string `json:"id"` Title string `json:"title"` Artist string `json:"artist"` Price float64 `json:"price"` } ``` ### 向response中写入返回数据 可以通过调用`gin.Context`的`IndentedJSON`方法来向response中写入数据, ```go // getAlbums responds with the list of all albums as JSON. func getAlbums(c *gin.Context) { c.IndentedJSON(http.StatusOK, albums) } ``` ### 解析request中的数据 可以通过`gin.Context`的`BindJSON`方法来将请求体中的数据解析到对象中。 ```go // postAlbums adds an album from JSON received in the request body. func postAlbums(c *gin.Context) { var newAlbum album // Call BindJSON to bind the received JSON to // newAlbum. if err := c.BindJSON(&newAlbum); err != nil { return } // Add the new album to the slice. albums = append(albums, newAlbum) c.IndentedJSON(http.StatusCreated, newAlbum) } ``` ### 将请求的endpoint注册到server中 可以将各个请求的处理handler注册到server中,并在指定端口上运行server: ```go func main() { router := gin.Default() router.GET("/albums", getAlbums) router.POST("/albums", postAlbums) router.Run("localhost:8080") } ``` 上述示例中,分别向`/albums`路径注册了GET和POST的处理handler,并在`localhost:8080`上对服务进行监听。 ## golang generic ### 不使用泛型的代码编写 如果不使用泛型,那么对于不同数值类型的求和,需要编写多个版本的代码,示例如下: ```go // SumInts adds together the values of m. func SumInts(m map[string]int64) int64 { var s int64 for _, v := range m { s += v } return s } // SumFloats adds together the values of m. func SumFloats(m map[string]float64) float64 { var s float64 for _, v := range m { s += v } return s } ``` 上述针对int64和float64的版本,编写了两个独立的函数 ### 使用泛型的代码编写 对于泛型方法的编写,其相对普通方法多了`类型参数`,在对泛型方法进行调用时,可以传递类型参数和普通参数。 对于每个`parameter type`,其都有对应的`type constraint`。每个`type constraint`都制定了在调用泛型方法时,可以对`parameter type`指定哪些类型。 `type parameter`通常都带代表一系列类型的集合,但是在编译时type parameter则是代表由调用方传递的`type argument`类型。如果type argument类型不满足type constraint的要求,那么该代码则不会被成功编译。