Java程序员学习Go语言入门笔记-index2

15 篇文章 0 订阅
本篇内容:指针、数组、切片、map、结构体

复合类型

指针pointer

默认值:nil(nil相当于Java中的null)

内存和指针的区别

内存:内存的内容
指针:内存的编号,也叫地址

package main

import "fmt"

func main() {
	// 声明方式1:取地址
	var i int = 1
	var p1 *int = &i // 指向一个合法内存,"*int"是指针类型,"&"取地址
	fmt.Printf("i = %v, p1 = %v\n", i, p1)
	*p1 = 100                 // "*pointer"操作的是引用
	fmt.Printf("i = %v\n", i) // 100

	// 声明方式2:new函数
	var p2 *int = new(int) // *int类型的p2指针指向匿名的int变量
	fmt.Printf("p2 = %v\n", p2)
}

变量作为函数参数是值传递,指针是引用传递

package main

import "fmt"

func change(i int) {
	i = 100
	fmt.Println("change i = ", i)
}

func changeInMemory(p *int) {
	*p = 100
	fmt.Println("changeInMemory i = ", *p)
}

func main() {
	var i int = 1

	// 变量做函数参数是值传递,指针是引用传递
	change(i)
	fmt.Println("i = ", i)
	changeInMemory(&i)
	fmt.Println("i = ", i)
}

输出结果
在这里插入图片描述

数组

声明和初始化

package main

import "fmt"

func main() {
	// 声明
	var arr1 [3]int // 声明一个长度为3的数组
	fmt.Printf("arr1长度 = %d, arr1容量 = %d\n",
		len(arr1), cap(arr1)) // 数组的长度与容量相等

	// 初始化
	arr2 := [3]int{1, 2, 3}
	fmt.Println("arr2 = ", arr2)
	arr3 := [...]int{1, 2, 3} // 自动确定数组长度
	fmt.Println("arr3 = ", arr3)
	arr4 := [3]int{1} // 部分初始化,其余元素以0补全
	fmt.Println("arr4 = ", arr4)
	arr5 := [3]int{1: 1} // 通过下标初始化,其余元素以0补全
	fmt.Println("arr5 = ", arr5)
}

在这里插入图片描述

数组作为函数参数是值传递

package main

import "fmt"

func change(arr [3]int) { // [3]int和[4]int是不同类型
	arr[1] = 0
	fmt.Println("change arr =", arr)
}

func changeByPointer(p *[3]int) {
	(*p)[1] = 0
	fmt.Println("changeByPointer arr =", *p)
}

func main() {
	arr := [3]int{1, 2, 3}
	change(arr) // 值传递
	fmt.Println("arr =", arr)
	changeByPointer(&arr) // 引用传递
	fmt.Println("arr =", arr)
}

在这里插入图片描述

切片slice

不定长度数组

切片通过声明或截取数组or切片创建

声明

package main

import "fmt"

func main() {
	// 切片声明方式1
	var s1 []int // 相比数组少了长度
	fmt.Println("s1 =", s1)
	s2 := []int{}
	fmt.Println("s2 =", s2)

	// 切片声明方式2:make函数:make(切片类型, 长度, 容量),容量可以省略,与长度的值相等
	var s3 = make([]int, 3, 3)
	fmt.Println("s3 =", s3)
	s4 := make([]int, 3, 3)
	fmt.Println("s4 =", s4)

	// 声明并初始化
	s5 := []int{1, 2, 3}
	fmt.Printf("切片s5长度 = %d, 容量 = %d\n", len(s5), cap(s5)) // 长度与容量并不一定相等
}

在这里插入图片描述

截取

package main

import "fmt"

func main() {
	var arr [5]int = [5]int{1, 2, 3, 4, 5}
	/**
	截取数组,格式:arr[a:b:c],
	从下标a开始截取数组arr直到下标b,不包括b,是一个左开右闭区间,
	a可以省略默认值为0,b可以省略默认值为数组arr的长度,c可以省略与b值相等
	切片s的长度是b-a,容量是c-a
	*/
	var s1 = arr[1:3:5]
	fmt.Println("s1 =", s1)
	fmt.Printf("切片s1长度 = %d, 容量 = %d\n", len(s1), cap(s1))

	var s2 = arr[:]
	fmt.Println("s2 =", s2)
	fmt.Printf("切片s2长度 = %d, 容量 = %d\n", len(s2), cap(s2))
}

在这里插入图片描述

切片最终指向的还是底层的数组

修改切片,原数组也会跟着改变

package main

import "fmt"

func main() {
	var arr [5]int = [5]int{1, 2, 3, 4, 5}
	var s = arr[1:3:5]
	s[1] = 100                // 与数组一样通过下标取元素
	fmt.Println("s =", s)     // [2 100]
	fmt.Println("arr =", arr) // 原数组被修改[1 2 100 4 5]
}

在这里插入图片描述

切片作为函数参数是引用传递

这个很好理解,因为它指向的是底层数组

append:append(slice, x)

package main

import "fmt"

func main() {
	var arr [3]int = [3]int{1, 2, 3}
	var s = arr[:]
	fmt.Printf("切片s长度 = %d, 容量 = %d\n", len(s), cap(s)) // 切片s长度 = 3, 容量 = 3
	/**
	append(slice, x),往切片末尾追加"x",返回新的切片s
	当元素的数量达到切片容量的上限,通常以两倍容量扩容
	*/
	s = append(s, 4)
	fmt.Printf("切片s长度 = %d, 容量 = %d\n", len(s), cap(s)) // 切片s长度 = 4, 容量 = 6
}

在这里插入图片描述

copy:copy(target, source)

package main

import "fmt"

func main() {
	var s1 = []int{100, 200, 300, 400, 500}
	var s2 = []int{1, 2, 3}
	copy(s1, s2)            // copy(target, source),将source覆盖粘贴到target
	fmt.Println("s1 =", s1) // [1 2 3 400 500]
}

map(映射、字典)

map[keyType]valueType{}

package main

import "fmt"

func main() {
	// map
	var m = map[string]int{}
	m["xiaoming"] = 100
	fmt.Println("m =", m)
	fmt.Println("len(m) =", len(m)) // 有len()无cap()

	// 判断是否存在key: value, ok := map[key]
	value, ok := m["xiaoming"]
	fmt.Printf("value = %d, ok = %v\n", value, ok)

	// 删除key,内置函数delete(map, key)
	delete(m, "xiaoming")
	fmt.Println("m =", m)
	
	// map作为函数参数时是值传递...
}

在这里插入图片描述

结构体

type 结构体名称 struct {}

package main

import "fmt"

// 自定义结构体User
type User struct {
	id       int // 结构体成员变量,不需要通过var声明,普通变量需要
	username string
	password string
}

func main() {
	// 结构体初始化方式1:顺序初始化,每个成员都必须初始化
	var user1 User = User{1, "yw", "123"}
	fmt.Println("user1 =", user1)

	// 结构体初始化方式2:指定成员初始化,未指定成员默认值
	user2 := User{id: 2, username: "hh"}
	fmt.Println("user2 =", user2)

	// 声明→赋值成员变量
	var user3 = User{}
	user3.id = 3
	user3.username = "ym"
	fmt.Println("user3 =", user3)

	// 结构体可以通过==或!=比较
	fmt.Println("user3 = user2 ok?", user3 == user2)

	// 结构体指针声明方式1:指向有效内存
	var user4P = &User{id: 4}
	user4P.username = "xx" // 可以和变量一样访问成员
	(*user4P).password = "123"
	fmt.Println("user4P =", user4P)

	// 结构体指针声明方式2:通过new申请
	var user5P = new(User)
	user5P.id = 5
	fmt.Println("user5P =", user5P)

	// 结构体变量作为函数参数是值传递...
}

在这里插入图片描述

可见性

符号首字母大写相当于public修饰,小写相当于private。

不当之处,请予指正。

上一篇:Java程序员学习Go语言入门笔记-index1
下一篇:Java程序员学习Go语言入门笔记-index3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作为一名 Java 程序员,了解硬件层面的内存知识是非常重要的。在 NUMA 架构下,内存的访问速度会受到影响,因此了解 NUMA 架构的内存分布和访问方式,可以帮助程序员优化程序的性能。 NUMA 架构是一种多处理器架构,其中每个处理器都有自己的本地内存和一组本地 I/O 设备。这些处理器通过一个快速互联网络连接在一起,共享全局内存和 I/O 设备。 在 NUMA 架构下,内存被分割成多个本地内存区域和全局内存区域。本地内存区域是指与处理器直接相连的内存区域,访问速度最快。全局内存区域是指被所有处理器共享的内存区域,访问速度相对较慢。 程序员需要了解的是,当一个线程在处理器上执行时,它会优先访问本地内存区域,如果需要访问全局内存区域,则会通过互联网络访问,这会导致访问速度变慢。因此,在程序设计时,需要尽可能地减少线程之间的共享内存,避免出现频繁的跨处理器访问全局内存的情况。 另外,程序员还需要了解内存对齐的概念。在 NUMA 架构下,由于不同处理器的内存访问速度不同,如果内存没有对齐,则会导致不同处理器之间的数据传输速度不一致,进而影响程序的性能。因此,在程序设计时,需要注意内存对齐的问题,尽可能地将数据放在相邻的内存位置,避免出现不必要的跨处理器数据传输。 总之,了解 NUMA 架构的内存分布和访问方式是非常重要的,可以帮助程序员优化程序的性能。程序员需要注意线程之间的共享内存和内存对齐的问题,尽可能地减少跨处理器访问全局内存的情况,提高程序的执行效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值