Go学习之路:更多类型:struct、slice 和映射(DAY 2)

news2024/11/27 0:18:19

文章目录

    • 前引
    • 更多类型:struct、slice 和映射
      • 1、指针
      • 2.1、结构体/结构体命名(一)
      • 2.2、结构体/对象访问、指针访问、初始化规则(二)
      • 3、数组
      • 4.1、切片/初始化切片
      • 4.2、切片/切片引用数组
      • 4.3、切片/切片的length和capacity
      • 4.4、切片/Nil切片
      • 4.5、切片/设置为二维切片/切片添加元素
      • 5、Range
      • 6.1、映射/map的初始化
      • 6.2、映射/映射的基本操作
      • 7.1、函数/函数值
      • 7.2、函数/函数闭包


前引


周天辣 昨天全员核酸没有阳性 如果再有两天阴性的话 就有机会楼栋能解封啦 最好的情况希望能出现 周二能回去!

在寝室里闲着也是闲着 还是学一下go吧 把剩下的基础的给学完
希望好运伴随!
希望未来顺利


更多类型:struct、slice 和映射


1、指针


go语言中仍旧保持了有指针的特性 这个还是非常欣慰的
准确来说应该和c/c++差别并不大 唯一的差别是不能进行指针运算

下面是例子
111.go

package main

import "fmt"

func main() {
	i, j := 1, 2
	p := &i
	fmt.Println(*p, i, j)
	p = &j
	fmt.Println(*p, i, j)
	*p = 3
	fmt.Println(*p, i, j)
}

运行效果
在这里插入图片描述


2.1、结构体/结构体命名(一)


命名方式相比于c语言有所不一样 其他的基本大致相同
type name struct

然后从这里我自己去搜了10分钟的资料
发现go语言的内存分配和c++ 完全不一样
第一点 c++需要自己手动解决内存分配问题 而go语言是自动回收
第二点 go语言会自动分析该对象是否是需要分配内存 决定于内存逃逸行为 go语言的内存分析我刚刚又花了20分钟看了一下 发现不像是c++那样 什么对象是动态分配的 什么是静态分配(在栈中)定义的时候 自己都清楚 而是取决于当前对象是否能被外部引用 go语言还是偏向于分配栈对象的 但是对于没有办法确认是否会被外部引用时 只能放于堆中 用GC来管理

关于内存分配问题 这个后面还要花很多事情去研究研究 下面写了很多 来看究竟结构体的内存分配情况 以及结构体的初始化


111.go

package main

import "fmt"

type Node struct {
	val int
	next *Node
}

var global_ptr *Node

func PtrGo() {
	global_ptr = &Node{}
	global_ptr.val = -1
}

func main() {
	// 初始化1
	var dummynode1 Node
	dummynode1.val = -1 //初始化为0后 再赋值
	ptr1 := &dummynode1
	fmt.Printf("%d %p %s%p %s%p %s\n", dummynode1.val, dummynode1.next, "ptr addr:", &ptr1, "struct addr:", ptr1 , "way 3")

	//初始化2
	dummynode2 := Node{-1, nil}
	ptr2 := &dummynode2
	fmt.Printf("%d %p %s%p %s%p %s\n", dummynode2.val, dummynode2.next, "ptr addr:", &ptr2, "struct addr:", ptr2, "way 3")

	//初始化3
	dummynode3 := new(Node)
	dummynode3.val = -1
	ptr3 := dummynode3
	fmt.Printf("%d %p %s%p %s%p %s\n", dummynode3.val, dummynode3.next, "ptr addr:", &ptr3, "struct addr:", ptr3, "way 3")

	//初始化4
	PtrGo()
	fmt.Printf("%d %p %s%p %s%p %s\n", global_ptr.val, global_ptr.next, "ptr addr:", &global_ptr, "struct addr:", global_ptr, "way 4")
}

运行效果
在这里插入图片描述


2.2、结构体/对象访问、指针访问、初始化规则(二)


结构体不管是指针还是直接对象访问结构体内部值 都是通过.符号来访问 不用指针->来访问了
第二个 初始化规则 上面的方式已经写完了初始化的方式

111.go

package main

import "fmt"

type Node struct {
	val int
	next *Node
}

func main() {
	var dummynode1 = Node{-1, nil}
	fmt.Println(dummynode1)

	var dummynode2 = Node{val : -1}
	fmt.Println(dummynode2)

	var dummynode3 = Node{next : nil}
	dummynode3.val = -1
	fmt.Println(dummynode3)

	dummynode4 := Node{-1, nil}
	fmt.Println(dummynode4)

	dummynode5 := new(Node)
	dummynode5.val = -1
	fmt.Println(*dummynode5)
}

运行效果
在这里插入图片描述


3、数组


构造方式和c语言类似 声明方式仍旧是golang化
简单的例子应用

package main

import "fmt"

func main() {
	var strs [2]string
	strs[0] = "Hello,"
	strs[1] = "World!"
	fmt.Println(strs[0], strs[1])
}

运行效果
在这里插入图片描述


数组的初始化办法
下面有这几种

111.go

package main

import (
	"fmt"
)

func main() {
	var nums1 [10]int = [10]int {1, 2, 3}
	for i := 0; i < 10; i++ {
		fmt.Printf("%d ", nums1[i])
	}
	fmt.Println()

	var nums2 = [10]int{1, 2, 3}
	for _, num := range nums2 {
		fmt.Printf("%d ", num)
	}
	fmt.Println()

	nums3 := [...]int{1, 2, 3}
	for _, num := range nums3 {
		fmt.Printf("%d ", num)
	}
	fmt.Println()

	nums4 := [10]int{0:1, 1:2, 2:3}
	for _, num := range nums4 {
		fmt.Printf("%d ", num)
	}
	fmt.Println()

	var nums5 [10]int
	nums5[0] = 1
	nums5[1] = 2
	nums5[2] = 3
	for _, num := range nums5 {
		fmt.Printf("%d ", num)
	}
	fmt.Println()
}

运行效果
在这里插入图片描述


4.1、切片/初始化切片


切片在还没有学习Go语言的时候就听说了其鼎鼎大名
所以我们还是来接触一下

slice的底层实现 本质还是根据的数组的底层 可以说用指针来表示数组的开始位置
三个数据结构支持slice 指针 size capacity
我认为如果是从数组切分出来的切片 不扩容 此时开销是最小的
但是如果要append元素 此时可以将其看作是c++ vector 本质上扩容的机制还是另外申请容量


切片初始化的方法很多 为了后面使用起来更得心应手 还是挨个挨个列出来吧

111.go

package main

import (
	"fmt"
)

func main() {
	//初始化1 刚开始为空切片nil
	slice1 := []int{}
	fmt.Println("before append, length:", len(slice1), ", capacity:", cap(slice1))
	for i := 0; i < 10; i++ {
		slice1 = append(slice1, i)
	}
	fmt.Println("after append 10 elems, length:", len(slice1), ", capacity:", cap(slice1))
	for _, num := range slice1 {
		fmt.Printf("%d ", num)
	}
	fmt.Println("\n")

	nums2 := [10]int {1, 2, 3, 4, 5}
	slice2 := nums2[:4] //初始化2 左闭右开 0 - 3 size 4 cap 10
	slice3 := nums2[1:] //初始化3 左闭右开 1 - 10 size 9 cap 9
	slice4 := nums2[0:4:5] //初始化4 左闭右开 0 - 3 size 4 cap 5(5 - 0)
	slice5 := nums2[:] //初始化5 左闭右开 0 - 10 size 10 cap 10
	fmt.Println("slice2 length:", len(slice2), ", capacity:", cap(slice2))
	fmt.Println("slice3 length:", len(slice3), ", capacity:", cap(slice3))
	fmt.Println("slice4 length:", len(slice4), ", capacity:", cap(slice4))
	fmt.Println("slice5 length:", len(slice5), ", capacity:", cap(slice5))

	slice6 := make([]int, 0, 10) //初始化6 size 0 cap 10
	var slice7 = make([]int, 0, 10) // 初始化7 size 0 cap 10
	var slice8[]int = make([]int, 0, 10) // 初始化8 size 0 cap 10
	fmt.Println("slice6 length:", len(slice6), ", capacity:", cap(slice6))
	fmt.Println("slice7 length:", len(slice7), ", capacity:", cap(slice7))
	fmt.Println("slice8 length:", len(slice8), ", capacity:", cap(slice8))
}

运行效果
在这里插入图片描述


4.2、切片/切片引用数组


切片本质上就是指向底层的数组 可以是一开始就生成切片对象 也可以是生成了数组后 再在切片上面切
如果刚开始切片是基于数组 那么修改切片 本质就是修改数组 数组和切片共享的是同一块内存
而如果当切片append扩容后 超过了之前的切片的capacity 此时就会像vector一样 另外找一块内存地址 并且将当前的内容复制过去 此时切片其实本质和之前的数组就已经没关系了 下面例子可以很清晰的表示


111.go

package main

import (
	"fmt"
)

func main() {
	nums := [...]int {1, 2, 3, 4, 5}
	slice := nums[:]
	fmt.Println("before append, slice length:", len(slice), ", capacity:", cap(slice))
	fmt.Println("before modify:")
	for index, num := range nums {
		fmt.Printf("nums2[%d]:%d slice[%d]:%d\n", index, num, index, slice[index])
	}


	for i := 0; i < len(nums); i++ {
		slice[i] = i + 100
	}
	fmt.Println("after modify:")
	for index, num := range nums {
		fmt.Printf("nums2[%d]:%d slice[%d]:%d\n", index, num, index, slice[index])
	}

	slice = append(slice, 0)
	fmt.Println("after append, slice length:", len(slice), ", capacity:", cap(slice))
	for i := 0; i < 5; i++ {
		slice[i] = i + 10
	}
	for index, num := range nums {
		fmt.Printf("nums2[%d]:%d slice[%d]:%d\n", index, num, index, slice[index])
	}
}


运行效果
在这里插入图片描述


4.3、切片/切片的length和capacity


切片的length表示 当前切片中实际存在的长度
切片的cap表示 当前切片可扩容的长度

切片如果基于 cap 可以扩容 当length == cap时 扩容则是2倍扩容
扩容底层有机制 后面我再详细看看

但是如果切片基于其他切片 则cap最大只能是其他切片的cap 无法额外分配内存扩容


获取切片的length是由len()获取 capacity是由cap()获取


4.4、切片/Nil切片


如果是空切片 例如用var slice1 []int生成切片
则为Nil切片 切片仅仅能和Nil切片作比较 不能与其他切片做比较

111.go

package main

import "fmt"

func main() {
	var slice1 []int
	if slice1 == nil {
		fmt.Println("Nil Slice")
	} else {
		fmt.Println("Non-Nil Slice")
	}
}

运行效果
在这里插入图片描述


4.5、切片/设置为二维切片/切片添加元素


切片使用范围更多 当作vector
append 添加元素

二维切片 [][]string{}

	slice := [][]string{}
	slice = append(slice, []string{})
	fmt.Println(len(slice[0]), cap(slice[0]))

5、Range


对于切片或者有序序列

可以Range 用法如下 可用_代替range不用的值

package main

import "fmt"

func main() {
	slice := [][]string{}
	slice = append(slice, []string{})
	for index, str := range slice {
		fmt.Println(index, str)
	}

	for _, str := range slice {
		fmt.Println(str)
	}

	for index, _ := range slice {
		fmt.Println(index)
	}
}


6.1、映射/map的初始化


就像是c++中的map 底层是用红黑树实现的
初始化map的方式 map[key_type]value_type

111.go

package main

import "fmt"

func main() {
	map_ := map[string]int{}
	var m = make(map[string]int)
	map_["gogo"] = 1
	map_["thanks"] = 2
	m["gogo"] = 1
	m["thanks"] = 2

	fmt.Println(map_["gogo"], map_["thanks"])
	fmt.Println(m["gogo"], m["thanks"])
}

6.2、映射/映射的基本操作


下面的操作包括 插入值 删除值 查找值

package main

import "fmt"

func main() {
	map_ := map[string]int{}
	map_["gogo"] = 1
	map_["thanks"] = 2

	elem, ok := map_["gogo"]
	fmt.Println(elem, ok)

	elem, ok = map_["go"]
	fmt.Println(elem, ok)

	map_["gogo"] = 3
	elem, ok = map_["gogo"]
	fmt.Println(elem, ok)

	delete(map_, "gogo")
	elem, ok = map_["gogo"]
	fmt.Println(elem, ok)
}

运行效果
在这里插入图片描述


7.1、函数/函数值


函数可以生成为类似于c++的可执行函数对象 或者可以捆绑的执行函数对象

package main

import "fmt"

func mul(x int, z int) int {
	return x * z
}

func mulfunc(func_ func(int, int) int, z int) int {
	return func_(3, 5) * z
}

func main() {
	funcobj := func(x, y int) int {
		return x * y
	}

	fmt.Println(funcobj(2, 3))
	fmt.Println(mul(funcobj(2, 3), 20))
	fmt.Println(mulfunc(funcobj, 20))
}

运行效果
在这里插入图片描述


7.2、函数/函数闭包


刚刚仔细去看了一下 发现并没有那么好理解

用我的话来解释一下 闭包内部声明的参数 其参数的声明期是和函数闭包对象的生命期一样的
并且返回一个匿名函数 之后匿名函数也可以使用之前声明的函数对象

下面是简单的使用例子 后续复杂的使用还要再琢磨琢磨
111.go

package main

import "fmt"

func add() func() int {
	i := 0
	return func() int {
		i += 1
		return i
	}
}

func deleter(x int) func(x int) int {
	i := 100
	return func(x int) int {
		i -= x
		return i
	}
}

func main() {
	Adder := add()
	fmt.Println(Adder())
	fmt.Println(Adder())

	Deleter := deleter(10)
	fmt.Println(Deleter(20))
	fmt.Println(Deleter(30))	
}


运行效果
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/42432.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

React Context源码是怎么实现的呢

目前来看 Context 是一个非常强大但是很多时候不会直接使用的 api。大多数项目不会直接使用 createContext 然后向下面传递数据&#xff0c;而是采用第三方库&#xff08;react-redux&#xff09;。 想想项目中是不是经常会用到 connect(...)(Comp) 以及 <Provider value{s…

非互联网客户收入近6成,阿里云进入新周期

近日&#xff0c;阿里巴巴发布了截至2022年9月30日止季度&#xff08;2023财年第二季度&#xff0c;阿里财年从每年4月1日至第二年3月31日&#xff09;业绩。 在除去阿里内部使用的额度&#xff0c;抵销跨分部交易后&#xff0c;阿里云业务分部&#xff08;包括阿里云和钉钉&am…

【web前端期末大作业】基于html+css+javascript+jquery技术设计的音乐网站(44页)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

【华为上机真题 2022】字符串加密

&#x1f388; 作者&#xff1a;Linux猿 &#x1f388; 简介&#xff1a;CSDN博客专家&#x1f3c6;&#xff0c;华为云享专家&#x1f3c6;&#xff0c;Linux、C/C、云计算、物联网、面试、刷题、算法尽管咨询我&#xff0c;关注我&#xff0c;有问题私聊&#xff01; &…

【Linux】基本指令(三)

文章目录sort 指令find 指令which 指令alias 指令grep 指令top 指令zip/unzip指令tar 指令bc 指令unname 指令history 指令shutdown 指令热键补充sort 指令 &#x1f495; Linux sort 命令用于将文本文件内容加以排序并且可针对文本文件的内容&#xff0c;以行为单位来排序。 …

03 探究Kubernetes工作机制的奥秘

自动化的运维管理&#xff1a;探究Kubernetes工作机制的奥秘 文章目录1. 云计算时代的操作系统2. kubernets 的基本架构3.节点内部的结构3.1 master 节点3.2 node 节点4. Kubernetes 的大致工作流程5.插件有哪些&#xff1f;5.1 重要的插件6. kubernetes 架构思维导图7. 思考的…

制作一个简单HTML校园网页(HTML+CSS)学校网站制作 校园网站设计与实现

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

RabbitMQ工作队列

工作队列(又称任务队列)的主要思想是避免立即执行资源密集型任务&#xff0c;而不得不等待它完成。 相反我们安排任务在之后执行。我们把任务封装为消息并将其发送到队列。在后台运行的工作进程将弹出任务并最终执行作业。当有多个工作线程时&#xff0c;这些工作线程将一起处…

电商购物平台的不断完善

目录 1.java编译环境的创建&#xff0c;与所需要用到的插件 第一个电商平台 1.初步思路&#xff1a; 2.确定java类 3.源码分析 成果&#xff1a; 第二个电商购物平台 代码&#xff1a; 最终的成果&#xff1a; 1.java编译环境的创建&#xff0c;与所需要用到的插件 (1…

链夹式烟苗注水移栽机的总体设计

目 录 1 引言 1 1.1课题来源及研究的目的和意义 1 1.2农艺要求 1 1.3链夹式烟苗注水移栽机的发展现状 1 1.4研究内容 3 2 链夹式烟苗注水移栽机的设计方案 4 2.1链夹式烟苗注水移栽机总体方案设计思路 4 2.2链夹式烟苗注水移栽机工作原理 5 3 链夹式烟苗注水移栽机具体设计 6 3…

带你入门HTML+CSS网页设计,编写网页代码的思路

带你入门HTMLCSS网页设计&#xff0c;编写网页代码的思路 这篇文章主要给大家详细解释一下这些代码的作用和意义&#xff0c;以及编写网页代码的格式与思路。 下面我贴上html代码&#xff1a; <!--HTML--> <div> <h2>这是我的第一个网页</h2> <p&…

Metabase学习教程:仪表盘-3

自定义联动&#xff1a;选择当人们单击仪表盘中的图表时会发生什么 您可以设置仪表盘部件以将用户导航到仪表盘、保存的问题和URL&#xff0c;并使用仪表盘中的值更新目标仪表盘的筛选器&#xff0c;或参数化指向外部站点的链接。 Metabase提供了一些简单的构建块&#xff0c…

谷粒学院——Day08【课程发布-课程大纲和课程发布】

富文本编辑器Tinymce 一、Tinymce可视化编辑器 参考 https://panjiachen.gitee.io/vue-element-admin/#/components/tinymce https://panjiachen.gitee.io/vue-element-admin/#/example/create 二、组件初始化 Tinymce是一个传统javascript插件&#xff0c;默认不能用于V…

MySQL安装部署

1、卸载mariadb 查看是否有默认的mariadbrpm -qa|grep mariadb 如果有&#xff0c;卸载rpm -e --nodeps mariadb-libs-5.5.56-2.el7.x86_64&#xff0c;然后删除etc目录下的my.cnfrm -rf /etc/my.cnf&#xff08;注意这里需要确定tar包里是否有默认的cnf文件&#xff0c;在su…

NLP实践!文本语法纠错模型实战,搭建你的贴身语法修改小助手 ⛵

&#x1f4a1; 作者&#xff1a;韩信子ShowMeAI &#x1f4d8; 深度学习实战系列&#xff1a;https://www.showmeai.tech/tutorials/42 &#x1f4d8; 自然语言处理实战系列&#xff1a;https://www.showmeai.tech/tutorials/45 &#x1f4d8; 本文地址&#xff1a;https://sho…

AI智能机器人的测评以及部署

作为业内人士&#xff0c;今天给大家测评下电销机器人。究竟是什么样的电销机器人才是让客户满意的&#xff1f; 咱们先来说说电销机器人到底是什么&#xff1f; 相信很多人都对电销机器人没有过多的了解。甚至还有人会问&#xff1b;“什么&#xff1f;机器人&#xff1f;啥样…

两万字详细解读AQS,你真的了解它吗?

1、JUC的由来 synchronized 关键字是JDK官方人员用C代码写的&#xff0c;在JDK6以前是重量级锁。Java大牛 Doug Lea对 synchronized 在并发编程条件下的性能表现不满意就自己写了个JUC&#xff0c;以此来提升并发性能&#xff0c;本文要讲的就是JUC并发包下的AbstractQueuedSy…

Listen、Attention、Spell模型

LAS是一个做语音识别的经典seq2seq模型&#xff0c;主要分为三个部分Listen、Attention、Spell Listen Listen部分就是一个encoder。 输入声学特征向量&#xff0c;提取信息、消除噪声&#xff0c;输出向量。 encoder可以是RNN 也可以是CNN。比较常见的是先用CNN&#xff0…

第三章变量

第三章变量 查看javaAPI文档的网址&#xff1a; https://www.matools.com/ 3.1程序中号的使用 1&#xff09;当左右两边都是数值型时&#xff0c;则做加法运算 2&#xff09;当左右两边有一方为字符串&#xff0c;则做拼接运算 3&#xff09;运算顺序从左到右 System,out.prin…

Springboot+vue校园新闻网站idea

将系统需求进行分析总结&#xff0c;系统需求如下&#xff1a; 系统可以运行在Windows操作系统平台上&#xff0c;并通过友好的界面进行管理 系统用户分为游客&#xff0c;登录用户&#xff0c;管理员 游客可以浏览新闻 游客可以浏览评论 管理员具有用户所有的权限 管理员还可以…