Go --- 编程知识点及其注意事项

new与make

二者都是用于内存分配,当声明的变量是引用类型时,不能给该变量赋值,因为没有分配空间。

我们可以用new和make对其进行内存分配。

  • 首先说说new

new函数定义

func new(Type) *Type

传入一个类型,返回一个指向分配好该类型的地址的指针,并将变量赋零值。

在敲代码时并不常用。

  • 再来说说make

make也是用于内存分配的,但是和new不同。

make有明确的分工,它只能用于slice、map、channel。因为三者都是引用类型,所以并不需要返回指针,而且不会置零值。

make与new都是分配堆空间。

数据定义

1、当给返回值命名时,如果已经默认了返回值名称,则所有返回值都要有默认名。如

myFunc(x,y int)(sum int,error)

是不被允许的,编译会报错,如果一个返回值有名称则也需要用()括起来。

2、结构体比较

一般来说结构体是可以使用“==”比较的,只有当结构体定义时属性顺序不同,或者结构体中有不可比较的类型,如map和slice。

带有map和slice的结构体可以使用reflect库下的

DeepEqual(x, y any) bool

进行比较。

不同结构体实例化出来的对象比较结果必然也会不同。

3、string与nil类型

nil 可以用作 interface、function、pointer、map、slice 和 channel 的“空值”,但是不能作为string类型的空值。

所以nil不能作为string类型的返回值。

4、常量

变量在程序运行中分配内存,而常量在编译器预处理阶段就开始分配。

内存四区:
  • 栈区

空间较小,要求数据读写性能高,数据存放时间较短暂。由编译器自动分配和释放,存放函数的参数值、函数的调用流程方法地址、局部变量等(局部变量如果产生逃逸现象,可能会挂在在堆区)

  • 堆区

空间充裕,数据存放时间较久。一般由开发者分配及释放(但是Golang中会根据变量的逃逸现象来选择是否分配到栈上或堆上),启动Golang的GC由GC清除机制自动回收。

  • 全局区

    • 全局变量的开辟是在程序在main之前就已经放在内存中。而且对外完全可见。即作用域在全部代码中,任何同包代码均可随时使用,在变量会搞混淆,而且在局部函数中如果同名称变量使用:=赋值会出现编译错误。
    • 全局变量最终在进程退出时,由操作系统回收。我们在开发的时候,尽量减少使用全局变量的设计
    • 常量区也归属于全局区,常量为存放数值字面值单位,即不可修改。或者说的有的常量是直接挂钩字面值的。
  • 代码区

存放要运行的代码片段。

程序运行前的准备工作:

1、操作系统把物理硬盘代码load到内存

2、操作系统把c代码分成四个区

3、操作系统找到main函数入口执行

在golang中,常量是无法取出地址的,因为字面量符号并没有地址而言。

数组与切片

  • 切片的底层也是数组
  • 切片是可动态扩增长度的数组
  • 初始化方式不同,数组声明时需要先确定容量len=cap,并且会使用0值填充,切片初始化时使用一般使用make,len和cap可以自定义不同的值。

定义切片的几种方式:

	var (
		a []int               // nil切片
		b = []int{}           // 空切片
		c = []int{1, 2, 3}    //三个元素,len=3,cap=3
		d = c[:2]             //两个元素,len=2,cap=3
		e = c[:2:cap(c)]      //两个元素,len=2,cap=3
		f = c[:0]             //没有元素,len=0,cap=3
		g = make([]int, 3)    //三个元素,len=3,cap=3
		h = make([]int, 2, 3) //两个元素,len=2,cap=3
	)

拼接

两个slice在append的时候,记住需要进行将第二个slice进行...打散再拼接。

使用new定义的slice返回的是切片指针,不能直接进行append,需要使用解引用后使用,不如用make。

map

1、赋值问题

Go map如果value是结构体,那么赋值的时候不允许使用map直接给结构体赋值。

原因:说法多种多样,可以分为以下几个点:

1)map作为一个封装好的数据结构,由于它底层可能会由于数据扩张而进行迁移,所以拒绝直接寻址,避免产生野指针;

2)map中的key在不存在的时候,赋值语句其实会进行新的k-v值的插入,所以拒绝直接寻址结构体内的字段,以防结构体不存在的时候可能造成的错误;

3)这可能和map的并发不安全性相关

  • x = y 这种赋值的方式,你必须知道 x的地址,然后才能把值 y 赋给 x。
  • 但 go 中的 map 的 value 本身是不可寻址的,因为 map 的扩容的时候,可能要做 key/val pair迁移
  • value 本身地址是会改变的
  • 不支持寻址的话又怎么能赋值呢

解决办法:

  • 二次赋值
  • 使用结构体指针

2、遍历赋值问题

如果map的value是指针类型,那么不要使用foreach,因为foreach中指针会始终指在最后一个元素的位置。

原因:

go foreach 中的指针变量在每次迭代中都会被重复使用。如果迭代变量在“for”语句之外声明,则执行后它们的值将是最后一次迭代的值.

解决办法:

使用for而不是foreach。

interface

1、赋值问题

比如说:

type People interface {
	Speak(string) string
}

type Stduent struct{}

func (stu *Stduent) Speak(think string) (talk string) {
	if think == "love" {
		talk = "You are a good boy"
	} else {
		talk = "hi"
	}
	return
}

那么能不能这么赋值呢?

var peo People = Stduent{}

答案是不行

Stduent does not implement People

可以这么理解,实现接口的是结构体的引用不是结构体本身。

接口分为两种:空接口和非空接口。

  • 先来看空接口

就是没有定义任何方法的接口。

如:

type EmptyInterface interface {   
}

空接口结构体在Go语言中的定义为

type eface struct {      //空接口
    _type *_type         //类型信息
    data  unsafe.Pointer //指向数据的指针(go语言中特殊的指针类型unsafe.Pointer类似于c语言中的void*)
}

根据这个定义来看看这个问题:

	var stu *Stduent
	var peo People = stu

想一想这个peo会不会是nil?

答案是不是,因为eface定义中data是nil但是_type不是nil,所以peo不是nil。

  • 再来看看非空接口

Go中的定义为:

type iface struct {
  tab  *itab
  data unsafe.Pointer
}

itab里面包含了interface的一些关键信息,比如method的具体实现。

2、inteface{}与*interface{}的区别

type S struct {
}

func f(x interface{}) {
}

func g(x *interface{}) {
}

func main() {
	s := S{}
	p := &s
	f(s) //A
	g(s) //B 运行出错
	f(p) //C
	g(p) //D 运行出错
}

Go语言是强类型语言,interface{}作为参数可以传入指针和结构体,*interface{}作为参数只能传入 *interface{}。

channel

特性

go 1.21.6 windows/amd64

  • 给一个nil channel发送数据,会造成死锁
  • 从一个nil channel取出数据,也会造成死锁
  • 往一个已经close的channel发送数据,会报panic
  • 但是从一个已经close的channel取出,不会报panic,如果缓冲区中为空,则返回一个零值
  • 无缓冲的channel是同步的,而有缓冲的channel是非同步的

口诀是:“空读写死锁,写关闭异常,读关闭空零”。
注意使用goroutine时也要注意死锁问题啊

WaitGroup

WaitGroup与goroutine的竞速问题:

问题描述:

const N = 10
var wg = &sync.WaitGroup{}
func main() {

    for i:= 0; i< N; i++ {
        go func(i int) {
            wg.Add(1)
            println(i)
            defer wg.Done()
        }(i)
    }

    wg.Wait()
}

结果不唯一,代码存在风险, 所有go未必都能执行到。

就是还没等到Add函数执行,goroutine已经完成了。

解决办法就是将Add函数放在goroutine外,wg.Done在goroutine 内。

大部分内容来自:语雀-刘丹冰Aceld-Go修养之路

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Nacos部署(一)Linux部署Nacos2.3.x单机环境

&#x1f60a; 作者&#xff1a; 一恍过去 &#x1f496; 主页&#xff1a; https://blog.csdn.net/zhuocailing3390 &#x1f38a; 社区&#xff1a; Java技术栈交流 &#x1f389; 主题&#xff1a; Nacos部署&#xff08;一&#xff09;Linux部署Nacos2.3.x单机环境 ⏱️…

鸿蒙开发学习【地图位置服务组件】

简介 移动终端设备已经深入人们日常生活的方方面面&#xff0c;如查看所在城市的天气、新闻轶事、出行打车、旅行导航、运动记录。这些习以为常的活动&#xff0c;都离不开定位用户终端设备的位置。 当用户处于这些丰富的使用场景中时&#xff0c;系统的位置定位能力可以提供…

深度解析:Elasticsearch写入请求处理流程

版本 Elasticsearch 8.x 原文链接&#xff1a;https://mp.weixin.qq.com/s/hZ_ZOLFUoRuWyqp47hqCgQ 今天来看下 Elasticsearch 中的写入流程。 不想看过程可以直接跳转文章末尾查看总结部分。最后附上个人理解的一个图。 从我们发出写入请求&#xff0c;到 Elasticsearch 接收请…

应急响应实战笔记03权限维持篇(7)

第7篇&#xff1a;常见WebShell管理工具 攻击者在入侵网站时&#xff0c;通常要通过各种方式写入Webshell&#xff0c;从而获得服务器的控制权限&#xff0c;比如执行系统命令、读取配置文件、窃取用户数据&#xff0c;篡改网站页面等操作。 本文介绍十款常用的Webshell管理工…

图论基础|深度优先dfs、广度优先bfs

dfs 与 bfs 区别 提到深度优先搜索&#xff08;dfs&#xff09;&#xff0c;就不得不说和广度优先搜索&#xff08;bfs&#xff09;有什么区别 先来了解dfs的过程&#xff0c;很多录友可能对dfs&#xff08;深度优先搜索&#xff09;&#xff0c;bfs&#xff08;广度优先搜索…

K8S之DaemonSet控制器

DaemonSet控制器 概念、原理解读、应用场景概述工作原理典型的应用场景介绍DaemonSet 与 Deployment 的区别 解读资源清单文件实践案例 概念、原理解读、应用场景 概述 DaemonSet控制器能够确保K8S集群所有的节点都分别运行一个相同的pod副本&#xff1b; 当集群中增加node节…

【嵌入式】Docker镜像构建指南:引领应用部署的革新之路

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟。提供嵌入式方向的学习指导、简历面…

绘制韦恩图

主要源于跟着Cell学作图 | 12.韦恩图(Vennerable包)-CSDN博客&#xff0c;增加了相关数据转换的处理。 韦恩图与upset差异 upset图&#xff1a;多个集合交集可视_upset图r语言代码自定义交集顺序-CSDN博客 rm(list ls()) #构建模型数据 group1 <- rep(c("1",…

AcWing 796. 子矩阵的和

这个题的重点是仿照一维的数组&#xff0c;所以a[N][N]也是从1索引开始的。画个图举个例子就非常清晰了 之所以不好理解是因为没画格子&#xff0c;一个格子代表一个点&#xff0c;就很好理解了。 java代码&#xff1a; import java.io.*; public class Main{static int N 1…

Java为什么是值传递?

Java为什么是值传递&#xff1f; 在我们调用方法的时候&#xff0c;通常会传递参数&#xff0c;那我们到底传递的是对象本身&#xff0c;还是仅仅是对象的拷贝对象呢&#xff1f; 先搞懂两个概念&#xff0c;形参和实参 形参和实参 实参&#xff08;实际参数&#xff0c;Ar…

【热门话题】ECMAScript vs JavaScript:理解两者间的联系与区别

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 ECMAScript vs JavaScript&#xff1a;理解两者间的联系与区别1. ECMAScript&am…

Java设计模式之单例模式(多种实现方式)

虽然写了很多年代码&#xff0c;但是说真的对设计模式不是很熟练&#xff0c;虽然平时也会用到一些&#xff0c;但是都没有深入研究过&#xff0c;所以趁现在有空练下手 这章主要讲单例模式&#xff0c;也是最简单的一种模式&#xff0c;但是因为spring中bean的广泛应用&#…

车载测试项目实践 USD诊断 CANoe工具使用

本周末2天的时间&#xff0c;可以线下带大家对车载项目&#xff1a; uds诊断进行实操训练和CANoe工具的灵活使用 本博主从事新能源汽车的研发部&#xff0c;主要是嵌入式方面的&#xff0c;对车载测试的底层逻辑非常熟悉。 需要项目或者CANoe工具实操的可以关注并私信我

解决长尾问题,BEV-CLIP:自动驾驶中复杂场景的多模态BEV检索方法

解决长尾问题&#xff0c;BEV-CLIP&#xff1a;自动驾驶中复杂场景的多模态BEV检索方法 理想汽车的工作&#xff0c;原文&#xff0c;BEV-CLIP: Multi-modal BEV Retrieval Methodology for Complex Scene in Autonomous Driving 链接&#xff1a;https://arxiv.org/pdf/2401.…

算法思想总结:位运算

创作不易&#xff0c;感谢三连支持&#xff01;&#xff01; 一、常见的位运算总结 标题 二、位1的个数 . - 力扣&#xff08;LeetCode&#xff09; 利用第七条特性&#xff1a;n&&#xff08;n-1&#xff09;干掉最后一个1&#xff0c;然后每次都用count去统计&#xff…

MySQL数据库的下载和安装以及命令行语法学习

MySQL数据库的下载和安装以及命令行语法学习 学习MYSQL&#xff0c;掌握住基础的SQL句型&#xff08;创建数据库、查看数据库列表、数据增、删、改、查等操作类型&#xff09; 首先要知道MySQL下载和安装方法&#xff1a; 提示&#xff1a;别嫌啰嗦&#xff0c;对于一个初识MY…

vue-cli3中拉取vue-cli2

vue-cli3中拉取vue-cli2 拉取 2.x 模板 (旧版本) Vue CLI > 3 和旧版使用了相同的 vue 命令&#xff0c;所以 Vue CLI 2 (vue-cli) 被覆盖了。如果你仍然需要使用旧版本的 vue init 功能&#xff0c;你可以全局安装一个桥接工具&#xff1a; npm install -g vue/cli-init…

linux源配置:ubuntu、centos;lspci与lsmod命令区别

1、ubuntu源配置 1&#xff09;先查电脑版本型号: lsb_release -c2&#xff09;再编辑源更新&#xff0c;源要与上面型号对应 参考&#xff1a;https://midoq.github.io/2022/05/30/Ubuntu20-04%E6%9B%B4%E6%8D%A2%E5%9B%BD%E5%86%85%E9%95%9C%E5%83%8F%E6%BA%90/ /etc/apt/…

MUNIK第二届功能安全及自动驾驶研讨会将在沪召开

2024年4月26日,由上海秒尼科技术服务有限公司(以下简称“Munik”)联合Parosoft主办的“第二届功能安全及自动驾驶研讨会”将在上海虹桥隆重开幕。 据了解,本次功能与自动驾驶安全研讨会,将聚焦在ISO 26262标准体系下,自动驾驶新形势下各个零部件供应商如何满足功能安全等相关重…

移除和替换任何内容:AI 驱动的图像修复工具 | 开源日报 No.204

Sanster/IOPaint Stars: 15.1k License: Apache-2.0 IOPaint 是一款由 SOTA AI 模型驱动的图像修复工具。 该项目解决了从图片中移除任何不需要的对象、瑕疵或人物&#xff0c;以及擦除和替换图片上任何内容&#xff08;由稳定扩散技术支持&#xff09;的问题。 完全免费且开…