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" 了。

相关文章
|
4月前
|
存储 JavaScript Java
(Python基础)新时代语言!一起学习Python吧!(四):dict字典和set类型;切片类型、列表生成式;map和reduce迭代器;filter过滤函数、sorted排序函数;lambda函数
dict字典 Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。 我们可以通过声明JS对象一样的方式声明dict
324 1
|
8月前
|
存储 JSON 安全
Go语言切片,使用技巧与避坑指南
Go语言中的切片(Slice)是动态引用数组的高效数据结构,支持扩容与截取。本文从切片基础、常用操作到高级技巧全面解析,涵盖创建方式、`append`扩容机制、共享陷阱及安全复制等内容。通过代码示例详解切片特性,如预分配优化性能、区分`nil`与空切片、处理多维切片等。掌握这些核心知识点,可编写更高效的Go代码。
278 2
|
4月前
|
存储 Java Go
【Golang】(3)条件判断与循环?切片和数组的关系?映射表与Map?三组关系傻傻分不清?本文带你了解基本的复杂类型与执行判断语句
在Go中,条件控制语句总共有三种if、switch、select。循环只有for,不过for可以充当while使用。如果想要了解这些知识点,初学者进入文章中来感受吧!
208 1
|
7月前
|
数据采集 机器学习/深度学习 存储
Go语言实战案例 - 找出切片中的最大值与最小值
本案例通过实现查找整数切片中的最大值与最小值,帮助初学者掌握遍历、比较和错误处理技巧,内容涵盖算法基础、应用场景及完整代码示例,适合初学者提升编程能力。
|
8月前
|
Go 索引
Go语言中使用切片需要注意什么?
本文详细讲解了Go语言中切片(Slice)的使用方法与注意事项。切片是对数组连续片段的引用,具有灵活的操作方式。文章从定义与初始化、长度与容量、自动扩容、共享底层数组、复制、边界检查、零值到拼接等方面展开,并配以示例代码演示。通过学习,读者可深入了解切片的工作原理及优化技巧,避免常见陷阱,提升编程效率与代码质量。
211 2
|
9月前
|
人工智能 Go
[go]Slice 切片原理
本文详细介绍了Go语言中的切片(slice)数据结构,包括其定义、创建方式、扩容机制及常见操作。切片是一种动态数组,依托底层数组实现,具有灵活的扩容和传递特性。文章解析了切片的内部结构(包含指向底层数组的指针、长度和容量),并探讨了通过`make`创建切片、基于数组生成切片以及切片扩容的规则。此外,还分析了`append`函数的工作原理及其可能引发的扩容问题,以及切片拷贝时需要注意的细节。最后,通过典型面试题深入讲解了切片在函数间传递时的行为特点,帮助读者更好地理解和使用Go语言中的切片。
287 0
|
4月前
|
存储 安全 Java
【Golang】(4)Go里面的指针如何?函数与方法怎么不一样?带你了解Go不同于其他高级语言的语法
结构体可以存储一组不同类型的数据,是一种符合类型。Go抛弃了类与继承,同时也抛弃了构造方法,刻意弱化了面向对象的功能,Go并非是一个传统OOP的语言,但是Go依旧有着OOP的影子,通过结构体和方法也可以模拟出一个类。
288 1
|
6月前
|
Cloud Native 安全 Java
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
403 1
|
6月前
|
Cloud Native Go API
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
480 0
|
6月前
|
Cloud Native Java Go
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
321 0

热门文章

最新文章