Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】(4)

简介: Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】

Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】(3)https://developer.aliyun.com/article/1534260

5.7.2、指针类型接收者

       指针类型的接收者由一个结构体的指针组成,由于指针的特性,调用方法时修改接收者指针的任意成员变量,在方法结束后,修改都是有效的。

type person struct{
    name string
    age int8
    city string
}
 
// 构造器
func newPerson(name,city string,age int8) *person{
    return &person{
        name : name,
        city : city,
        age : age,
    }
}
 
// person 的方法
func (p person) eat(){
    fmt.Println("人会吃饭")
}
 
// 指针类型的接收者
func (p *person) setName(name string){
    p.name = name
}
 
func main(){
    p := newPerson("张三","北京",22)
    p.eat() // 人会吃饭
    p.setName("李四")
    fmt.Printf("%#v\n", p) // &main.person{name:"李四", age:22, city:"北京"}
}

注意:结构体是值类型的,并不是引用类型!所以当方法的接收者为指针类型时,才能真正操作结构体实例,否则就相当于拷贝了一份,在方法里自娱自乐。

5.7.3、指针类型接收者

这就是自娱自乐的场景,如果希望使用方法修改结构体实例的属性,那么一定不能使用这种方法。

type person struct{
    name string
    age int8
    city string
}
 
// 构造器
func newPerson(name,city string,age int8) *person{
    return &person{
        name : name,
        city : city,
        age : age,
    }
}
 
// person 的方法
func (p person) eat(){
    fmt.Println("人会吃饭")
}
 
// 非指针类型的接收者
func (p person) setName(name string){
    p.name = name
}
 
func main(){
    p := newPerson("张三","北京",22)
    p.eat() // 人会吃饭
    p.setName("李四")
    fmt.Printf("%#v\n", p) // &main.person{name:"张三", age:22, city:"北京"}
}
 

5.8、嵌套结构体

一个结构体中可以嵌套包含另一个结构体或结构体指针:

type Person struct{
    name string
    age int8
    addr Address
}
 
type Address struct{
    province string
    city string
}
 
func main(){
    p := Person{
        name :"张三",
        age : 22,
        addr : Address{
            province: "山西省",
            city : "晋中",
        },
    }
    fmt.Printf("%#v\n", p) // main.Person{name:"张三", age:22, addr:main.Address{province:"山西省", city:"晋中"}}
}

5.9、结构体的继承

type Animal struct{
    category string
}
 
func (a *Animal) move(){
    fmt.Printf("%s会移动",a.category)
}
 
type Dog struct{
    feet int8
    *Animal
}
 
func main(){
    dog := Dog{
        feet : 4,
        Animal: &Animal{
            category : "狗",
        },
    }
    dog.move() // 狗会移动
}

5.10、结构体字段的可见性

结构体中字段大写开头表示可公开访问,小写表示私有。

5.11、结构体 JSON 序列化

       我们可以使用 "encoding/json" 包下的 json.Marshal() 函数将结构体转换为 JSON 字符串。该函数接受一个参数,即要转换的结构体对象。如果转换成功,它将返回一个包含JSON数据的字节切片和一个错误值。

注意结构体的属性必须都为公开的(属性首字母大写),否则无法序列化为 json!

package main
 
import (
    "encoding/json"
    "fmt"
)
 
//Student 学生
type Student struct {
  ID     int
  Gender string
  Name   string
}
 
func main() {
    student1 := Student{
        ID : 1,
        Gender: "男",
        Name : "刘海柱",
    }
  //JSON序列化:结构体-->JSON格式的字符串
  data, err := json.Marshal(student1)
  if err != nil {
    fmt.Println("json marshal failed")
    return
  }
  fmt.Println(string(data)) // {"ID":1,"Gender":"男","Name":"刘海柱"}
  
  //JSON反序列化:JSON格式的字符串-->结构体
  str := `{"ID":1,"Gender":"男","Name":"刘海柱"}`
  student2 := &Student{}
  err = json.Unmarshal([]byte(str), student2)
  if err != nil {
    fmt.Println("json unmarshal failed!")
    return
  }
  fmt.Printf("%#v\n",student2) // &main.Student{ID:1, Gender:"男", Name:"刘海柱"}
}

5.12、结构体标签 Tag

       Tag是结构体的元信息,可以在运行的时候通过反射的机制读取出来。 Tag在结构体字段的后方定义,由一对反引号包裹起来,具体的格式如下:

`key1:"value1" key2:"value2"`

       结构体tag由一个或多个键值对组成。键与值使用冒号分隔,值用双引号括起来。同一个结构体字段可以设置多个键值对tag,不同的键值对之间使用空格分隔

注意事项 为结构体编写Tag时,必须严格遵守键值对的规则。结构体标签的解析代码的容错能力很差,一旦格式写错,编译和运行时都不会提示任何错误,通过反射也无法正确取值。例如不要在key和value之间添加空格。

package main
 
import (
    "encoding/json"
    "fmt"
)
 
//Student 学生
type Student struct {
  ID     int `json:"id"`
  Gender string
  Name   string // 私有属性不能被 json 访问
}
 
func main() {
    student1 := Student{
        ID : 1,
        Gender: "男",
        Name : "刘海柱",
    }
  //JSON序列化:结构体-->JSON格式的字符串
  data, err := json.Marshal(student1)
  if err != nil {
    fmt.Println("json marshal failed")
    return
  }
  fmt.Println(string(data)) // {"id":1,"Gender":"男","Name":"刘海柱"}
}

       上面,我们给 ID 属性添加了一个标签 'json:"id"',这样当使用 json 序列化的时候就可以使用我们指定的字段名 "id" 了。

相关文章
|
10天前
|
Java 编译器 Go
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】(3)
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】
|
8月前
|
Go
Go 语言学习之map
Go 语言学习之map
37 0
|
Go
go语言基础数据结构学习 ---- 字典(map)
go语言基础数据结构学习 ---- 字典(map)
94 0
|
Go
Go——小白学习之map
map的使用,key值唯一,打印出是无序的,注意坐标(key)与数组坐标不一样 定义: m3 := map[int]string{1: "mile", 2: "go"} m3[1] = "litter" m3[3] = "gogogo"    //超出范围,错误 fmt.
942 0
|
1天前
|
监控 Go
go语言并发实战——日志收集系统(八) go语言操作etcd以及利用watch实现对键值的监控
go语言并发实战——日志收集系统(八) go语言操作etcd以及利用watch实现对键值的监控
go语言并发实战——日志收集系统(八) go语言操作etcd以及利用watch实现对键值的监控
|
1天前
|
存储 Go
Go 语言当中 CHANNEL 缓冲
Go 语言当中 CHANNEL 缓冲
|
1天前
|
中间件 Go
go语言后端开发学习(三)——基于validator包实现接口校验
go语言后端开发学习(三)——基于validator包实现接口校验
|
1天前
|
存储 Go 开发工具
go语言后端开发学习(二)——基于七牛云实现的资源上传模块
go语言后端开发学习(二)——基于七牛云实现的资源上传模块
|
1天前
|
JSON 算法 Go
go语言后端开发学习(一)——JWT的介绍以及基于JWT实现登录验证
go语言后端开发学习(一)——JWT的介绍以及基于JWT实现登录验证
|
1天前
|
Go 数据库
Go语言之GORM框架(四)——预加载,关联标签与多态关联,自定义数据类型与事务(完结篇)
Go语言之GORM框架(四)——预加载,关联标签与多态关联,自定义数据类型与事务(完结篇)