首页 > 其他分享 >【拓展】Go语言基础加强

【拓展】Go语言基础加强

时间:2023-04-05 14:13:00浏览次数:30  
标签:语言 fmt 拓展 切片 range Go 拷贝 main 变量

1、深浅拷贝

  • 浅拷贝:仅仅拷贝的是变量的值,没有对指向的空间进行任何的拷贝。
  • 深拷贝:将原有的变量的空间地址全部拷贝一份。

在 Go 语言中,变量的赋值操作默认是浅拷贝,即两个变量指向同一个内存地址。这意味着,如果修改其中一个变量的值,另一个变量的值也会发生变化。

对于复杂数据类型,如结构体和切片,我们有时需要进行深拷贝,即创建一个新的变量并将原变量的值复制到新变量中,而不是简单地复制指向原变量的指针。这样可以避免修改新变量的值对原变量造成影响。

(1) 对于结构体,可以使用结构体字面量进行深拷贝

package main

import "fmt"

type Person struct {
	name string
	age  int
}

func main() {
	p1 := Person{"zhangsan", 20}
	p2 := Person{p1.name, p1.age} // 深拷贝

	fmt.Println(p1, p2)
	fmt.Println(&p1.name, &p2.name)
}

代码输出内容:

{zhangsan 20} {zhangsan 20}
0xc000008078 0xc000008090

(2) 对于切片,可以使用内置的 copy 函数进行深拷贝

package main

import "fmt"

func main() {
	s1 := []int{1, 2, 3}
	s2 := make([]int, len(s1))
	copy(s2, s1)

	fmt.Println(s1, s2)
	fmt.Println(&s1[0], &s2[0])
}

代码输出内容:

[1 2 3] [1 2 3]
0xc000016138 0xc000016150

需要注意的是,如果切片中的元素是引用类型,则深拷贝只会复制指向原变量的指针,而不会复制指针所指向的值。这时,需要对每个元素进行深拷贝,以确保新变量中的元素与原变量中的元素互不影响。

2、切片传参

(1)切片作为函数参数可以修改切片中的元素,原因分析:

在Go语言中,切片是一种引用类型,它底层是一个指向数组的指针,同时也包含了长度和容量等信息。当我们将一个切片传递给一个函数时,实际上是将切片的引用(指针)传递给了函数,因此函数中对切片的任何修改都会影响到原切片。

(2)为什么在函数中使用append方法,不会改变原切片?
首先看一下案例:

package main

import "fmt"

func main() {
	m := make([]int, 5, 5)
	InitData(m)
	fmt.Println(m)
}

func InitData(m []int) {
	for i := 0; i < 5; i++ {
		m = append(m, i)
	}
}

以上代码是创建一个切片,使用函数对切片进行初始化操作,代码输出内容如下:

[0 0 0 0 0]

思考:我们使用append函数对切片做初始化了,为什么并没有改变切片的值呢?

答:在Go语言中,切片是一种引用类型。当我们将一个切片作为参数传递给函数时,实际上是将切片的引用传递给了函数。因此,函数中对切片的任何修改都会影响到原始切片。

但是,当我们使用append方法向切片中添加元素时,如果新的元素可以被容纳在原始切片的容量范围内,那么append方法会直接在原始切片中添加新元素,并返回一个指向原始切片的新切片。这个新切片与原始切片共享底层数组,但长度已经被更新为添加新元素后的长度。

如果新的元素无法被容纳在原始切片的容量范围内,那么append方法会创建一个新的底层数组,并将原始切片中的元素复制到新的底层数组中。然后,append方法会向新的底层数组中添加新元素,并返回一个指向新底层数组的新切片。这个新切片与原始切片不再共享底层数组。

因此,在函数中使用append方法,如果新元素可以被容纳在原始切片的容量范围内,那么原始切片会被修改。否则,原始切片不会被修改,而是返回一个指向新底层数组的新切片。

3、for range分析

  • 作用:用户遍历容器类型的数据,列如:数组、切片、map等。
  • range的本质是一个函数方法,使用时候可以加括号使用。
  • 修改range得到后的value,不影响原始切片或数组。

(1) range的本质是一个函数方法,使用时候可以加括号使用:

package main

import (
	"fmt"
)

func main() {
	array := [3]int{100, 200, 300}
	for i, v := range (array) { // i, v := range (array) 定义两个变量接收range函数返回值
		array[i] = 3
		fmt.Println(v)
	}
	fmt.Println(array)
}

代码输出内容:

100
200
300
[3 3 3]

(2)修改range得到后的value,不影响原始切片或数组:

package main

import "fmt"

type Class struct {
	name string
	age  int
}

func main() {
	stu1 := Class{"zhangsan", 1}
	stu2 := Class{"lisi", 10}
	stu3 := Class{"wangwu", 100}
	s := []Class{stu1, stu2, stu3}

	for _, values := range s {
		values.age = values.age + 10000 // 对每个age进行更新操作
	}
	fmt.Println(s)
}

代码输出内容:

[{zhangsan 1} {lisi 10} {wangwu 100}]

思路:我对每个age进行更新了,为什么输出时没有进行更新呢?
答案:range是一个函数,age只是对range函数中进行修改了,并不会影响到原切片值。

标签:语言,fmt,拓展,切片,range,Go,拷贝,main,变量
From: https://www.cnblogs.com/qinziteng/p/17289044.html

相关文章

  • Go语言入门4(切片)
    切片​ Go语言切片是一种建立在数组类型之上的抽象,它构建在数组之上并且提供更强大的能力和便捷。解决了数组长度不可变等缺陷声明切片​ 切片的数据结构非常小,只有三个字段:指向底层数组的指针,切片长度,切片容量。切片长度是指切片的真实长度,切片容量是指切片可扩展的最大长度,一......
  • 逍遥自在学C语言 | 关系运算符
    前言一、人物简介第一位闪亮登场,有请今后会一直教我们C语言的老师——自在。第二位上场的是和我们一起学习的小白程序猿——逍遥。二、构成和表示方式关系运算符的作用是判断符号两边大小的关系C语言中的关系运算符主要有六个,如下表所示运算符名称示例......
  • Go语言入门3(数组)
    数组​ 数组是具有相同唯一类型的一组已编号且长度固定的数据项序列(这是一种同构的数据结构);这种类型可以是任意的原始类型例如整形、字符串或者自定义类型(结构体、接口)。数组长度也是数组类型的一部分,所以[5]int和[10]int是属于不同类型的。⭐:在其他语言中数组大多是引用类......
  • c语言小技巧
    无符号右移 voidprintBinary(unsignedintn){   inti;   for(i=sizeof(n)*8-1;i>=0;i--){ //遍历整数的每一位       if((n>>i)&1){ //如果该位为1,则输出字符'1'           printf("1");       }......
  • C语言结构体大小分析
    title:C语言结构体大小分析author:saopigqwq233date:2022-04-05C语言结构体大小分析一,基本类型C语言自带的数据类型大小如下数据类型大小(字节)char1short2int4long4或8float4double8longdouble16二,自定义类型---structC语言除了......
  • 开源 文本到视频:Tune-A-Video 本周 star 增长数:1,050+,主语言:Python
    开源不到48小时获35kstar的推荐算法「GitHub热点速览转载自己笔记备用 非公开  原作者博客园 本周的热点除了GPT各类衍生品之外,还多了一个被马斯克预告过、在愚人节开源出来的推特推荐算法,开源不到2天就有了35k+的star,有意思的是,除了推荐算法本身之外,阅......
  • C语言 静态变量的初始化
    一、C程序的内存分布C程序由下面5部分组成正文段(.text):通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域属于只读。在代码段中,也有可能包含一些只读的常量,例如字符串常量等。初始化数据段(.data):通常是指用来存放程序中已初......
  • linux下c语言的crypt函数怎么用?
    linux的crypt最近学校布置了一个网安的小作业,要用到linux里面的这个crypt函数,写一篇总结一下。首先我们要了解这个函数是用来做什么的。密码影子文件中存储了每一个用户的用户明文和其单向哈希过的秘文cipher="$1$C68vnJ27$1ttFZ1/Rylq/xi350A0NI0";密码字段用\(id\)salt$......
  • 解决picgo上传图片到github失败的方法
    今天在typora上写笔记,发现图片不能上传到github上,网上找了几个方法,发现都不能解决问题,一直在报错,折腾一会才解决,下面分享我的解决问题过程:首先先检查自己配置是否有错,检查仓库名是否写错,是否带有空格,picgo空格默认的是‘_’,分支名字可以是main或master,token可以再生成一个复制......
  • go run、build、install、get的原理和区别
    学习go也有好些年头了,都没怎么研究过go的编译命令。真是惭愧。今天学习并记录下结论:gorun专门用来运行命令源码文件的命令,一般用来运行单个文件gobuild主要是用于测试编译。编译某个包或者项目,在当前目录下生成可执行文件goinstall编译并安装代码包或者源码文件的。go......