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

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

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

4.2、map 的基本使用

4.2.1、添加元素

开辟内存空间之后,直接用就完了:

map[key] = value

4.2.2、初始化时添加元素

map 也支持初始化的时候指定元素(key 和 value 之间用引号而不是等号):

    score := map[string]int{
        "李大喜": 88,
        "燕双鹰": 99,
    }
    fmt.Println(len(score)) // 1
    fmt.Println(score) // map[小明:98]

但是需要注意的是初始化后的 map 不能再重新开辟内存了,否则会把初始化的内容全部清空!

但是初始化后的 map 默认是没有固定容量的,所以可以继续进行扩展。

4.2.3、判断 key 是否存在

判断方法:

value, ok := map[key]

       返回两个值:第一个值是返回的该key对应的值,如果没有则为该值类型的初始值。第二个值为一个 bool 类型的值,表示状态(存在:true,不存在:false)。

    users := map[string]int{
        "李大喜": 88,
        "燕双鹰": 99,
    }
    value,status := users["谢永强"]
    if status{
        fmt.Println("存在该用户并且value =",value)
    }else{
        fmt.Println("不存在该用户")
    }

 如果不希望得到状态值,可以使用 _ 进行忽略,或者:

value = users["谢永强"]

因为在Go语言中,range关键字用于遍历map时,会返回两个值,一个是键(key),另一个是值(value)。如果我们只使用了变量接收键,而没有使用任何变量来接收值,则编译器会自动忽略值的部分,只输出键。

4.2.4、map 的遍历

Go 语言使用 for range 来遍历 map:

    users := map[string]int{
        "李大喜": 88,
        "燕双鹰": 99,
    }
    users["谢永强"] = 95
    for k,v := range users{
        fmt.Println(k,v)
    }

       可以看到,这一点 Go 语言做的要比 Java 简单很多很多!毕竟 Java 不支持返回多个返回值,除非封装成一个数组或者别的对象!

如果希望返回所有 value,可以这样:

delete(map, key)
​    for _,v := range users{
        fmt.Println(v)
    }

4.2.5、使用 delete 函数删除键值对

使用delete()内建函数从map中删除一组键值对的格式如下:

delete(map, key)

注意:之所以叫内建函数,是因为 delete 函数是定义在 buildin.go 文件中的。

5、结构体

       Go语言中没有“类”的概念,也不支持“类”的继承等面向对象的概念。Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性。Go 语言正是通过结构体来实现面向对象。

5.1、结构体的定义

type 类名 struct{
    字段名 字段类型
    字段名 字段类型
    //...
}

比如:

type person struct {
  name string
  city string
  age  int8
}

对于相同类型的字段可以写在一行:

type person struct {
  name city string
  age  int8
}

5.2、结构体的实例化

和声明内置类型一样,我们可以使用 var 声明结构体类型:

var 结构体实例 结构体类型

比如:

type person struct {
  name string
  city string
  age  int8
}
 
func main(){
    var p person
    p.name = "谢永强"
    p.city = "象牙山"
    p.age = 22
    fmt.Println(p) // {谢永强 象牙山 22}
    fmt.Printf("%#v",p) // main.person{name:"谢永强", city:"象牙山", age:22}
}

5.3、匿名结构体

在定义一些临时数据结构等场景下还可以使用匿名结构体:

func main(){
    var p struct{name string;age int;city string}
    p.name = "谢永强"
    p.city = "象牙山"
    p.age = 22
    fmt.Println(p) // {谢永强 象牙山 22}
    fmt.Printf("%#v",p) // struct { name string; age int; city string }{name:"谢永强", age:22, city:"象牙山"}
}

5.4、结构体的初始化

5.4.1、使用键值对初始化

我们可以使用键值对的形式来实例化结构体:

type person struct{
    name string
    age int8
    city string
}
 
func main(){
    p := person{
        name :"谢永强",
        age : 22,
        city : "象牙山",
    }
    fmt.Printf("%#v",p) // main.person{name:"谢永强", age:22, city:"象牙山"}
}

注意没有初始化的结构体,其成员变量都是对应其类型的初始值。

5.4.2、使用列表进行初始化

使用列表进行初始化有以下这些要求:

  • 必须初始化结构体的所有字段。
  • 初始值的填充顺序必须与字段在结构体中的声明顺序一致
type person struct{
    name string
    age int8
    city string
}
 
func main(){
    p := person{
        "谢永强",
        22,
        "象牙山",
    }
    fmt.Printf("%#v",p) // main.person{name:"谢永强", age:22, city:"象牙山"}
}

5.5、结构体内存布局

结构体占用一块连续的内存。

type test struct {
  a int8
  b int8
  c int8
  d int8
}
 
 
func main(){
    n := test{
      1, 2, 3, 4,
    }
    fmt.Printf("n.a %p\n", &n.a)
    fmt.Printf("n.b %p\n", &n.b)
    fmt.Printf("n.c %p\n", &n.c)
    fmt.Printf("n.d %p\n", &n.d)
}

运行结果:

n.a 0xc000014028
n.b 0xc000014029
n.c 0xc00001402a
n.d 0xc00001402b

注意空结构体是不占用空间的。

5.6、构造函数

Go语言的结构体没有构造函数,但是我们可以自己实现:

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,
    }
}
 
func main(){
    p := newPerson("张三","北京",22)
    fmt.Printf("%#v\n", p) // &main.person{name:"张三", age:22, city:"北京"}
}

5.7、方法与接受者

       Go语言中的方法是一种作用于特定类型变量的函数。这种特定类型变量叫做接收者。接收者的概念就类似于 Java 中的 this 。

方法与函数的区别是,函数不属于任何类型,方法属于特定的类型。

5.7.1、创建方法

func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {
    函数体
}
  • 接收者变量:在命名时,官方建议使用接受者类型名称首字母小写
  • 接收者类型:可以是指针类型和非指针类型
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 main(){
    p := newPerson("张三","北京",22)
    p.eat() // 人会吃饭
    fmt.Printf("%#v\n", p) // &main.person{name:"张三", age:22, city:"北京"}
}

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

相关文章
|
3天前
|
存储 监控 Go
【Go语言精进之路】构建高效Go程序:了解切片实现原理并高效使用
【Go语言精进之路】构建高效Go程序:了解切片实现原理并高效使用
16 3
|
3天前
|
设计模式 安全 Go
【Go语言精进之路】构建高效Go程序:零值可用、使用复合字面值作为初值构造器
【Go语言精进之路】构建高效Go程序:零值可用、使用复合字面值作为初值构造器
8 2
|
10天前
|
JSON Go 数据格式
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】(4)
Go 语言基础之指针、复合类型【数组、切片、指针、map、struct】
|
1月前
|
开发框架 安全 中间件
Go语言开发小技巧&易错点100例(十二)
Go语言开发小技巧&易错点100例(十二)
38 1
|
1天前
|
中间件 Go
go语言后端开发学习(三)——基于validator包实现接口校验
go语言后端开发学习(三)——基于validator包实现接口校验
|
1天前
|
存储 Go 开发工具
go语言后端开发学习(二)——基于七牛云实现的资源上传模块
go语言后端开发学习(二)——基于七牛云实现的资源上传模块
|
1天前
|
JSON 算法 Go
go语言后端开发学习(一)——JWT的介绍以及基于JWT实现登录验证
go语言后端开发学习(一)——JWT的介绍以及基于JWT实现登录验证
|
1月前
|
缓存 负载均衡 网络协议
使用Go语言开发高性能服务的深度解析
【5月更文挑战第21天】本文深入探讨了使用Go语言开发高性能服务的技巧,强调了Go的并发性能、内存管理和网络编程优势。关键点包括:1) 利用goroutine和channel进行并发处理,通过goroutine池优化资源;2) 注意内存管理,减少不必要的分配和释放,使用pprof分析;3) 使用非阻塞I/O和连接池提升网络性能,结合HTTP/2和负载均衡技术;4) 通过性能分析、代码优化、缓存和压缩等手段进一步提升服务性能。掌握这些技术能帮助开发者构建更高效稳定的服务。
|
1月前
|
Kubernetes Cloud Native Go
Golang深入浅出之-Go语言中的云原生开发:Kubernetes与Docker
【5月更文挑战第5天】本文探讨了Go语言在云原生开发中的应用,特别是在Kubernetes和Docker中的使用。Docker利用Go语言的性能和跨平台能力编写Dockerfile和构建镜像。Kubernetes,主要由Go语言编写,提供了方便的客户端库与集群交互。文章列举了Dockerfile编写、Kubernetes资源定义和服务发现的常见问题及解决方案,并给出了Go语言构建Docker镜像和与Kubernetes交互的代码示例。通过掌握这些技巧,开发者能更高效地进行云原生应用开发。
78 1
|
1月前
|
存储 关系型数据库 Go
【Go语言专栏】基于Go语言的RESTful API开发
【4月更文挑战第30天】本文介绍了使用Go语言开发RESTful API的方法,涵盖了路由、请求处理、数据存储和测试关键点。RESTful API基于HTTP协议,无状态且使用标准方法表示操作。在Go中,通过第三方库如`gorilla/mux`进行路由映射,使用`net/http`处理请求,与数据库交互可选ORM库`gorm`,测试则依赖于Go内置的`testing`框架。Go的简洁性和并发性使得它成为构建高效API的理想选择。