GO语言-07派生类型:map和结构体(上)

简介: 自己学习Go语言学习过程中的记录与总结,希望对你能有帮助。第七篇(上):学习Go语言的Map,以及使用type定义自己的类型,包括type+struct定义结构体
初心是记录和总结,自己学习Go语言的历程。如果能帮助到你,这是我的荣幸。

map

Map的概念在任何程序语言都一样,存储key-value这样的内容,通过key可以查到对应的valuekey是唯一的。

语法:
var map[key的类型]value的类型

例子:

//定义一个map,这时候没有初始化是不能直接使用的
var province map[string]string
province["ZheJiang"] = "浙江" //报错
未初始化的Map赋值会报错: panic: assignment to entry in nil map,说我们正在操作一个空的Map

panic指的是Go语言遇到一个异常时候强制执行让程序终止的操作

map初始化的几种方法

  • 使用make函数
  • 使用new定义一个指针,然后使用*解析地址赋给定义的map
  • 定义时同时赋值
//初始化方式一:使用make进行创建,初始指定容量为2
province = make(map[string]string, 2)
province["ZheJiang"] = "浙江"
province["ShangHai"] = "上海"
province["BeiJing"] = "北京"
// 初始化方式二:new返回的是一个指针
var province map[string]string
pointMap := new(map[string]string) // 返回的是一个map指针,指针是存地址的
province = *pointMap // *号的作用是解析地址
province["ZheJiang"] = "浙江"
province["ShangHai"] = "上海"
province["BeiJing"] = "北京"
// 我们手动给它初始化了,也是可以的
province := map[string]string{"JiangSu": "江苏", "SiChuan": "四川"}

查询map中是够包含某个键

基于map名[key名]的方式,会返回value和一个bool类型,通过bool可以判断是否含有这个键

_, ok := province["ZheJiang"] //_只是一个占位符
fmt.Println(ok)               //true

value, ok := province["ZheJiang"]
fmt.Println(value) //浙江
fmt.Println(ok) //true

遍历整个map

通过range的方式遍历Map,可以获得map的keyvalue。单独获取keyvalue,我们可以通过_我们可以舍去不需要的数据来实现,示例代码如下:

// 遍历Map
for key, value := range province {
   fmt.Println(key, value)
}

遍历Key

// 遍历Key
for key,_ := range province {
   fmt.Println(key)
}

遍历Value

// 遍历value
for _, value := range province {
   fmt.Println(value)
}

删除Map中的元素

使用内置函数delete,通过key删除map元素

delete(province, "ShangHai")

type关键字

使用type我们可以自定义类型。这很有必要,因为我们需要描述一件事的事情的时候是需要描述很多内容。就像人,这个人会有年龄,名字。我们需要把人的概念抽出来,然后就可以用人来形容世界上所有的人,因为我们将年龄,名字这种共性的东西抽出来,形成人的概念了。而go语言中并没有这个变量类型,只有int可以表示年龄,string可以表示名字。如何定义人这个类型呢?使用typestruct,先了解一下type

语法:

我们可以自定义类型,使用go语言提供type关键字,例如:

type myInt int

type是定义了一个全新的类型。我们可以基于内置的基本类型定义,上面的例子就是基于int定义的新类型myInt。现在我们准备回答这个类型怎么定义,通过type + struct

struct 结构体

结构体有点类似于Java定义的类,里面有成员变量和方法。恰恰,在Go语言中方法就是一个类型,所以这和Java的类很像!,这样有助于我们开始理解struct。拿个例子,定义一个person类型,它可以描述人的年龄和姓名。

语法:

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

解读:type是用来表示自定义类型的,struct可以帮助我们使用多个字段类型来组成类型名这个类型,其实我们就是在定义一个复合类型,这个类型的名字最终交类型名

定义person类型:

type person struct{
    name string //描述姓名
    age int //描述年龄
}

定义完成之后,我们来定义一个person类型的变量取名为people,当输出people的时候,我们会发现该类型中包含的类型都被自动初始化了。

var people person
fmt.Println(people) //{ 0}

定义的变量我们可以通过.的方式访问到结构体中的字段名,并给与一些赋值的操作。

//通过类型.字段名的方式结构体的字段
people.name = "chengyunlai"
people.age = 18
fmt.Println(people) // {chengyunlai 18}

使用new的方式定义

我们使用new的方式定义的时候,我们知道其实返回的是一个指针,所以people2其实是一个person类型的指针,里面存放的是地址,当我们打印的时候可以发现前面是带了个&符号。

那我们当然知道*是解析地址的作用,在前面加了个*,发现打印出来就是实际的值

// 定义2 使用new返回指针的方式定义
people2 := new(person)
fmt.Println(people2)        //&{ 0}
fmt.Println(*(people2))     //{ 0}
fmt.Println((*people2).age) // 0

其实不用这么麻烦,Go语言为我们准备了语法糖,看代码

people2.age = 18 // 相当于(*people2).age = 18
fmt.Println(people2.age)

结构体里放方法?

学过java的人,又了解过go语言中方法其实是一个类型的时候,会很开心的想到在结构体里放方法,比如说设置一个setter方法,通过方法传参的方式设置nameage

type person struct {
   name    string //描述姓名
   age     int    //描述年龄
   setNameAndAge func(p *person, name string, age int)
}
这个需要用到指针的知识,小伙伴们可以自己尝试,我就不挖坑了,因为我试过了。指针传递过来的地址保证了我们操作的是同一个地址。

解读:
这里我们定义了一个方法setName func(p *person, name string, age int),方法名为setName,因为go没有this的用法,所以我们把对操作,写进了第一个变量中,我们需要做的是给nameint赋值,所以还定义了两个传入的参数。

使用:

var people person //定义person类型的变量为people

people.setNameAndAge = func(p *person, name_ string, age_ int) {
   p.name = name_
   p.age = age_
   fmt.Printf("%p\n", p) //0xc0000543c0
}

people.setNameAndAge(&people, "张三", 15)
fmt.Printf("%p\n", &people) //0xc0000543c0
fmt.Println(people) //{张三 15 0xa4fc80}

解读:
由于我尝试在结构体中写方法,但是失败了,失败的原因看语法就能明白,里面只能定义。所以只能实例化(var people person),像people.字段名的方法进行方法的赋值(确实感觉笨笨的~),当然我们可以考虑将方法抽出来这样将方法名赋值就行。后面我们会说一下go语言应对这种情况的解决办法。但是我这个思想还是挺重要的

people.setNameAndAge(&people, "张三", 15)传入了操作的地址,以及我想赋值的变量值,由于我的方法已经定义好了,在方法中我特地打印了一下地址,可以发现两个打印输出的地址是一样的,这就是指针的作用。

最后输出了fmt.Println(people) //{张三 15 0xa4fc80} 发现尝试成功!

目录
相关文章
|
5天前
|
存储 JSON 监控
Viper,一个Go语言配置管理神器!
Viper 是一个功能强大的 Go 语言配置管理库,支持从多种来源读取配置,包括文件、环境变量、远程配置中心等。本文详细介绍了 Viper 的核心特性和使用方法,包括从本地 YAML 文件和 Consul 远程配置中心读取配置的示例。Viper 的多来源配置、动态配置和轻松集成特性使其成为管理复杂应用配置的理想选择。
23 2
|
3天前
|
Go 索引
go语言中的循环语句
【11月更文挑战第4天】
12 2
|
3天前
|
Go C++
go语言中的条件语句
【11月更文挑战第4天】
14 2
|
7天前
|
程序员 Go
go语言中的控制结构
【11月更文挑战第3天】
84 58
|
6天前
|
监控 Go API
Go语言在微服务架构中的应用实践
在微服务架构的浪潮中,Go语言以其简洁、高效和并发处理能力脱颖而出,成为构建微服务的理想选择。本文将探讨Go语言在微服务架构中的应用实践,包括Go语言的特性如何适应微服务架构的需求,以及在实际开发中如何利用Go语言的特性来提高服务的性能和可维护性。我们将通过一个具体的案例分析,展示Go语言在微服务开发中的优势,并讨论在实际应用中可能遇到的挑战和解决方案。
|
3天前
|
Go
go语言中的 跳转语句
【11月更文挑战第4天】
10 4
|
3天前
|
JSON 安全 Go
Go语言中使用JWT鉴权、Token刷新完整示例,拿去直接用!
本文介绍了如何在 Go 语言中使用 Gin 框架实现 JWT 用户认证和安全保护。JWT(JSON Web Token)是一种轻量、高效的认证与授权解决方案,特别适合微服务架构。文章详细讲解了 JWT 的基本概念、结构以及如何在 Gin 中生成、解析和刷新 JWT。通过示例代码,展示了如何在实际项目中应用 JWT,确保用户身份验证和数据安全。完整代码可在 GitHub 仓库中查看。
14 1
|
7天前
|
Go 数据处理 API
Go语言在微服务架构中的应用与优势
本文摘要采用问答形式,以期提供更直接的信息获取方式。 Q1: 为什么选择Go语言进行微服务开发? A1: Go语言的并发模型、简洁的语法和高效的编译速度使其成为微服务架构的理想选择。 Q2: Go语言在微服务架构中有哪些优势? A2: 主要优势包括高性能、高并发处理能力、简洁的代码和强大的标准库。 Q3: 文章将如何展示Go语言在微服务中的应用? A3: 通过对比其他语言和展示Go语言在实际项目中的应用案例,来说明其在微服务架构中的优势。
|
7天前
|
Go 数据处理 调度
探索Go语言的并发模型:Goroutines与Channels的协同工作
在现代编程语言中,Go语言以其独特的并发模型脱颖而出。本文将深入探讨Go语言中的Goroutines和Channels,这两种机制如何协同工作以实现高效的并发处理。我们将通过实际代码示例,展示如何在Go程序中创建和管理Goroutines,以及如何使用Channels进行Goroutines之间的通信。此外,本文还将讨论在使用这些并发工具时可能遇到的常见问题及其解决方案,旨在为Go语言开发者提供一个全面的并发编程指南。
|
5天前
|
Go 调度 开发者
探索Go语言中的并发模式:goroutine与channel
在本文中,我们将深入探讨Go语言中的核心并发特性——goroutine和channel。不同于传统的并发模型,Go语言的并发机制以其简洁性和高效性著称。本文将通过实际代码示例,展示如何利用goroutine实现轻量级的并发执行,以及如何通过channel安全地在goroutine之间传递数据。摘要部分将概述这些概念,并提示读者本文将提供哪些具体的技术洞见。