package main
import (
"encoding/json"
"fmt"
"reflect"
)
type Address struct {
City string `json:"city"`
Country string `json:"country"`
}
type User struct {
Username string `json:"username"`
Password string `json:"password"`
}
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Address Address `json:"address"`
// 这么写,JSON 会多一层
// User `json:"user"`
User
}
func (p Person) SayHello() {
fmt.Println("Hello, my name is", p.Name)
}
func main() {
person := Person{
Name: "Bob",
Age: 30,
Address: Address{
City: "London",
Country: "UK",
},
User: User{
Username: "bob1999",
Password: "pa55w0rd",
},
}
// 属性操作
fmt.Println("Name:", person.Name)
fmt.Println("Age:", person.Age)
fmt.Println("City:", person.Address.City)
fmt.Println("Country:", person.Address.Country)
fmt.Println("Username:", person.Username)
fmt.Println("Password:", person.Password)
fmt.Printf("%+v\n", person)
fmt.Printf("%#v\n", person)
// 方法调用
person.SayHello()
// 通过反射获取标签内容
t := reflect.TypeOf(person)
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
tag := field.Tag.Get("json")
fmt.Println(field.Name, ":", tag)
}
// JSON 序列化
jsonData, err := json.Marshal(person)
if err != nil {
fmt.Println(err)
}
fmt.Println("JSON:", string(jsonData))
}
// Name: Bob
// Age: 30
// City: London
// Country: UK
// Username: bob1999
// Password: pa55w0rd
// main.Person{name:"Bob", age:30, address:main.Address{city:"London", country:"UK"}, User:main.User{username:"bob1999", password:"pa55w0rd"}}
其他知识点:
-
字段名大小写问题:首字母小写的话,只有本包可以访问
-
Zero-value Struct
type Fruit struct { name string } var apple Fruit fmt.Println(apple) // {}
-
new 关键字
package main import "fmt" type Employee struct { Name string Age int } func main() { p := new(Employee) fmt.Println(p) // &{ 0} var p2 Employee fmt.Println(p2) // { 0} p3 := Employee{"Me", 30} fmt.Println(p3) // {Me 30} }
-
struct 字面量
type Person struct { Name string Age int Email string } p1 := Person{ Name: "Alice", Age: 25, Email: "alice@example.com", } p2 := Person {"Alice", 25, "alice@example.com"}
-
指针
-
匿名结构体
package main import ( "fmt" ) func main() { user := struct { username string }{ username: "admin", } fmt.Printf("%+v\n", user) // {username:admin} fmt.Printf("%#v\n", user) // struct { username string }{username:"admin"} fmt.Printf("%v\n", user) // {admin} fmt.Println(user) // {admin} }
场景:
- 定义一个临时结构体接收反序列化数据
- 内嵌结构体
-
匿名属性(或者应该叫啥,我也不知道)
- 内嵌类型不能重复,
- 前面的例子可以看出,可以直接访问匿名属性(结构体)内部属性,
- 但是如果同名就只能老老实实通过类型名字来访问了
package main import ( "fmt" ) type Book struct { string // book name (anno field) // syntax error: unexpected [, expected field name or embedded type // []Author Authors []Author // slice of authors Publisher } type Author struct { string // author name (anno field) } type Publisher struct { string // publisher name (anno field) } func main() { p := Book{ string: "Learning Python", Authors: []Author{ {string: "Stanley B.Lippman"}, {string: "Josée LaJoie"}, {"Barbara E.Moo"}, }, Publisher: Publisher{"人民邮电出版社"}, } p.string = "C++ Primer" // change attr fmt.Println(p) fmt.Printf("%v\n", p) fmt.Printf("%+v\n", p) fmt.Printf("%#v\n", p) fmt.Printf("%v\n", p.string) fmt.Printf("%v\n", p.Authors[0].string) fmt.Printf("%v\n", p.Publisher) fmt.Printf("%v\n", p.Publisher.string) } // {C++ Primer [{Stanley B.Lippman} {Josée LaJoie} {Barbara E.Moo}] {人民邮电出版社}} // {C++ Primer [{Stanley B.Lippman} {Josée LaJoie} {Barbara E.Moo}] {人民邮电出版社}} // {string:C++ Primer Authors:[{string:Stanley B.Lippman} {string:Josée LaJoie} {string:Barbara E.Moo}] Publisher:{string:人民邮电出版社}} // main.Book{string:"C++ Primer", Authors:[]main.Author{main.Author{string:"Stanley B.Lippman"}, main.Author{string:"Josée LaJoie"}, main.Author{string:"Barbara E.Moo"}}, Publisher:main.Publisher{string:"人民邮电出版社"}} // C++ Primer // Stanley B.Lippman // {人民邮电出版社} // 人民邮电出版社
-
将函数通过属性的方式定义
type FoodNameGetter func(string) string type Food struct { name string getter FoodNameGetter // declare function } pizza := Food{ name: "Pizza", getter: func(name string) string { // declare function body return "This is " + name + "." }, }
-
结构体比较
如果类型和值相同,就等于。
package main import "fmt" type Teacher struct { name string } type Student struct { name string } func main() { s1 := Student{"John"} s2 := Student{"John"} fmt.Println(s1 == s2) // true // invalid operation: s1 == t1 (mismatched types Student and Teacher) // t1 := Teacher{"John"} // fmt.Println(s1 == t1) }