匿名结构就像普通结构一样,但是它没有名称定义,因此不能在代码的其他地方引用。Go中的结构类似于C等其他语言中的结构。它们是字段的类型化集合,用于将数据分组在一起,以使我们作为程序员更易于管理。要创建匿名结构,只需在声明类型后立即实例化实例:
newCar := struct {
make string
model string
mileage int
}{
make: "Ford",
model: "Taurus",
mileage: 200000,
}
将其与创建结构的“常规”方式进行对比:
// declare the 'car' struct type
type car struct {
make string
model string
mileage int
}
// create an instance of a car
newCar := car{
make: "Ford",
model: "taurus",
mileage: 200000,
}
我经常使用匿名结构在HTTP处理程序中封装和解封JSON数据。如果一个结构只打算被使用一次,那么以这样一种方式声明它是有意义的,即使得开发人员不会试图再次使用它。看下面的代码。我们能够将HTTP请求直接解析到newCar结构中,而无需给结构命名。仍然可以通过点运算符访问所有字段,但是我们不必担心项目的另一部分尝试使用非预期类型。
func createCarHandler(w http.ResponseWriter, req *http.Request) {
defer req.Body.Close()
decoder := json.NewDecoder(req.Body)
newCar := struct {
Make string `json:"make"`
Model string `json:"model"`
Mileage int `json:"mileage"`
}{}
err := decoder.Decode(&newCar)
if err != nil {
log.Println(err)
return
}
makeCar(newCar.Make, newCar.Model, newCar.Mileage)
return
}
我经常看到使用map[string]interface{},而不是声明用于JSON解组的快速匿名结构。在大多数情况下,这是很糟糕的,原因如下:
func createCarHandler(w http.ResponseWriter, req *http.Request) {
myMap := map[string]interface{}{}
decoder := json.NewDecoder(req.Body)
err := decoder.Decode(&myMap)
if err != nil {
log.Println(err)
return
}
model, ok := myMap["model"]
if !ok {
fmt.Println("field doesn't exist")
return
}
modelString, ok := model.(string)
if !ok {
fmt.Println("model is not a string")
}
// do something with model field
}
如果使用正确,匿名结构可以清理您的API处理程序。他们提供的强类型输入同时仍是“一次性”解决方案,是一个强大的工具。