结构体是一个自定义的数据类型,是值类型
声明结构体
type 结构体名称 struct {
field_1 type
field_2 type
}
注意事项
- 字段声明语法同变量,示例:字段名 字段类型 
- 字段的类型可以为:基本类型、数组或引用类型 
- 创建一个结构体变量后,如果没有给字段赋值,都会对应一个默认值,规则如下: 
- 布尔类型默认为false 
- 数值类型默认为0 
- 字符串类型默认为空"" 
- 数组类型的默认值与它的元素类型相关,比如:Scores [3]int 默认值为:[0,0,0] 
- 指针、切片(slice)、map默认值都是nil,即还没有分配空间 
- 不同的结构体字段之间是独立的,互不影响,一个字段值的改变不会影响另外一个 
基本使用
package main
import "fmt"
type Stu struct {
    Name  string
    Age   int
    Score float32
    Ptr   *int              // 指针
    Array [3]int            // 数组
    Slice []string          // 切片
    Map1  map[string]string // map
}
func main() {
    // 结构体基本使用
    var student Stu
    student.Name = "宋江"
    student.Age = 20
    student.Score = 60
    fmt.Println(student)
    // 单独访问变量
    fmt.Printf("Name:%v,Age:%v,Score:%v\n", student.Name, student.Age, student.Score)
    // 给数组赋值
    student.Array = [3]int{1, 2, 0}
    student.Array[2] = 3
    // 给切片赋值,切片赋值必须make!!!
    student.Slice = make([]string, 3)
    student.Slice[0] = "卢俊义"
    student.Slice[1] = "吴用"
    student.Slice[2] = "公孙胜"
    student.Slice = append(student.Slice, "林超") // 切片超过定义范围,再追加需用append函数
    // 给map赋值,map赋值必须make!!!
    student.Map1 = make(map[string]string)
    student.Map1["no1"] = "吃饭"
    student.Map1["no2"] = "睡觉"
    student.Map1["no3"] = "打游戏"
    fmt.Println(student)
} 
   不同的结构体字段之间是独立性
package main
import "fmt"
type Stu struct {
    Name  string
    Age   int
    Score float32
}
func main() {
    // 不同的结构体字段之间是独立的,互不影响
    var student1 Stu
    student1.Name = "宋江"
    student1.Age = 20
    student1.Score = 60
    student2 := student1
    student2.Score = 70 // 此处元素值的改变并不会影响student1
    fmt.Println(student1)
    fmt.Println(student2)
} 
   创建结构体实例的四种方式
看代码注释,推荐第二种方式
package main
import "fmt"
type Person struct {
    Name string
    Age  int
}
func main() {
    // 第一种方式
    var person1 Person
    person1.Name = "宋江"
    person1.Age = 20
    fmt.Println(person1)
    // 第二种方式
    var person2 = Person{
        Name: "吴用",
        Age:  19,
    }
    fmt.Println(person2)
    // 第三种方式,person3是指针类型
    var person3 *Person = new(Person) // *Person可以省略不写
    (*person3).Name = "卢俊义"           // 可以省略为:person3.Name = "卢俊义",(*person3)等价于person3
    (*person3).Age = 21               // 可以省略为:person3.Age = 21,(*person3)等价于person3
    fmt.Println(*person3)
    // 第四种,person4算指针类型,可以直接赋值,也可以重新赋值
    var person4 *Person = &Person{ // *Person可以省略不写
        Name: "公孙胜",
        Age:  22,
    }
    person4.Name = "林冲" // 重写赋值,标准写法:(*person4).Name = "林冲",这里使用的是省略方式
    person4.Age = 23    // 重写赋值,标准写法:(*person4).Age = 23,这里使用的是省略方式
    fmt.Println(*person4)
} 
   结构体指针的使用
package main
import "fmt"
type Person struct {
    Name string
    Age  int
}
func main() {
    var person = Person{
        Name: "宋江",
        Age:  19,
    }
    personPtr := &person  // 定义一个指针
    personPtr.Name = "吴用" // 修改指针的Name,personPtr是省略方式
    (*personPtr).Age = 20 // 修改指针的Age,*personPtr是指针标准方式
    fmt.Println(person)
    fmt.Println(*personPtr)
} 
   结构体细节
- 结构体是用户单独定义的类型,和其他类型进行转换时需要有完全相同的字段(字段名、个数、类型) 
package main
import "fmt"
type Person struct {
    Name string
    Age  int
}
type Person1 struct {
    Name string
    Age  int
}
func main() {
    var person = Person{
        Name: "宋江",
        Age:  19,
    }
    // var person1 Person1 = person // 这种直接赋值是不行的,需要做强转
    var person1 Person1 = Person1(person) // 强转的前提是两个结构体必须完全一样
    fmt.Println(person)
    fmt.Println(person1)
} 
   - 结构体进行type重新定义(相当于取别名),Golang认为是新的数据类型,但是相互间可以强转 
package main
import "fmt"
type integer int // 新定义数据类型integer,相当于int的别名
func main() {
    var i integer = 10
    var j int
    // j = i // 直接赋值是不行,需要强转
    j = int(i)
    fmt.Println(i, "---", j)
} 
   - struct 的每个字段上,可以写上一个tag,该tag可以通过反射机制获取,常见的使用场景是json的序列化和反序列化 
package main
import (
    "encoding/json"
    "fmt"
)
type Person struct {
    Name string `json:"name"` // tag的作用是返回json后Name转换为name(首字母小写)
    Age  int    `json:"age"`
    As   string `json:"as"`
}
func main() {
    var persons = map[int]Person{
        0: {
            Name: "宋江",
            Age:  19,
            As:   "及时雨",
        },
        1: {
            Name: "吴用",
            Age:  20,
            As:   "神机军师",
        },
    }
    var personStr, err = json.Marshal(persons)
    if err != nil {
        fmt.Println("json转码错误", err)
    } else {
        fmt.Println(string(personStr))
    }
}返回:{"0":{"name":"宋江","age":19,"as":"及时雨"},"1":{"name":"吴用","age":20,"as":"神机军师"}}



















