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)
}