返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

5.2 数组

发布于 2024-10-12 19:15:47 字数 4059 浏览 0 评论 0 收藏 0

数组是单一内存块,并无其他附加结构。

  +---+---+---+----//---+----+
  | 0 | 1 | 2 | ... ... | 99 |   [100]int
  +---+---+---+----//---+----+
  
  • 数组长度必须是 非负整型常量 表达式。
  • 长度是数组类型组成部分。
  • 初始化多维数组,仅第一维度允许用 ...
  • 初始化复合类型,可省略元素类型标签。
  • 内置函数 lencap 都返回一维长度。
  • 元素类型支持 ==!= ,那么数组也支持。
  • 支持数组指针直接访问。
  • 支持获取元素指针。
  • 值传递,复制整个数组。
func main() {
	var d1 [unsafe.Sizeof(0)]int  // 编译期计算。
	var d2 [2]int                 // 元素类型相同,长度不同!
    
	d1 = d2
	     ~~ cannot use [2]int as type [8]int in assignment
}

灵活初始化方式。

func main() {
	var a [4]int                 // 元素自动初始化为零。
    
	b := [4]int{2, 5}            // 未提供初始值的元素自动初始化为 0。
	c := [4]int{5, 3: 10}        // 可指定索引位置初始化。
	d := [...]int{1, 2, 3}       // 编译器按初始化值数量确定数组长度。
	e := [...]int{10, 3: 100}    // 支持索引初始化,数组长度与此有关。
    
	fmt.Println(a, b, c, d, e)
}

/*

a: [0 0 0 0]
b: [2 5 0 0]
c: [5 0 0 10]
d: [1 2 3]
e: [10 0 0 100]

*/
func main() {
	type user struct {
		id   int
		name string
	}

	_ = [...]user{    // 这里不能省略。
		{1, "zs"},    // 元素类型标签可省略。
		{2, "ls"},
	}
}
func main() {
	// var x [2]int = {2, 5}
	//                ~~~~~~ syntax error

	// var y [...]int = [2]int{2, 5}
	//       ~~~~~ invalid use of [...] array (outside a composite literal)
}

多维数组依旧是连续内存存储。

func main() {
    x := [...][2]int{
        {1, 2},
        {3, 4},
    }
    
    y := [...][3][2]int{
        {
            {1, 2}, 
            {3, 4},
            {5, 6},
        },
        {
            {10, 11},
            {12, 13},
            {14, 15},
        },
    }
    
    fmt.Println(x, len(x), cap(x))  // 2, 2
    fmt.Println(y, len(y), cap(y))  // 2, 2
}

/*

(gdb) x/4xg &x
0xc000066df0:   0x0000000000000001      0x0000000000000002
0xc000066e00:   0x0000000000000003      0x0000000000000004

(gdb) x/12xg &y
0xc000066e30:   0x0000000000000001      0x0000000000000002
0xc000066e40:   0x0000000000000003      0x0000000000000004
0xc000066e50:   0x0000000000000005      0x0000000000000006
0xc000066e60:   0x000000000000000a      0x000000000000000b
0xc000066e70:   0x000000000000000c      0x000000000000000d
0xc000066e80:   0x000000000000000e      0x000000000000000f

*/

相等比较,须元素支持。

func main() {
	var a, b [2]int
	println(a == b)     // true

	c := [2]int{1, 2}
	d := [2]int{0, 1}
	println(c == d)     // false

	// var e, f [2]map[string]int
	// println(e == f) 
	//         ~~~~~~ [2]map[string]int cannot be compared
}

指针

注意区别不同指针及称谓。

  • 数组指针: &array ,指向整个数组的指针。
  • 元素指针: &array[0] ,指向某个元素的指针。
  • 指针数组: [...]*int{ &a, &b } ,元素是指针的数组。
func main() {
	d := [...]int{ 0, 1, 2, 3 }

	var p  *[4]int = &d       // 数组指针。
	var pe *int    = &d[1]    // 元素指针。

    p[0] += 10          // 相当于 (*p)[0]
	*pe += 20

	fmt.Println(d)
}

// [10 21 2 3]
func main() {
	a, b := 1, 2

	d := [...]*int{ &a, &b }   // 指针数组。
	*d[1] += 10                // d[1] 返回 b 指针。

	fmt.Println(d)
	fmt.Println(a, b)
}

// [0xc000014080 0xc000014088]
// 1 12

复制

鉴于数组传递会整个复制,可使切片或指针代替。

func val(d [3]byte) [3]byte {
	fmt.Printf("val: %p\n", &d)

	d[0] += 100
	return d
}

func ptr(p *[3]byte) *[3]byte {
	fmt.Printf("ptr: %p\n", p)

	p[0] += 200
	return p
}

func main() {
	 d := [...]byte{ 1, 2, 3 }
	d2 := d
	d3 := *(&d)

	fmt.Printf(" d: %p\n", &d)
	fmt.Printf("d2: %p\n", &d2)
	fmt.Printf("d3: %p\n", &d3)

	// ---------------------

	d4 := val(d)
	fmt.Printf("val.ret: %p\n", &d4)

	p := ptr(&d)
	fmt.Printf("val.ret: %p\n", p)	

	// ---------------------

	fmt.Printf("d: %v\n", d)
}

/*

      d: 0xc000014080
     d2: 0xc000014083
     d3: 0xc000014086

    val: 0xc00001409b
val.ret: 0xc000014098

    ptr: 0xc000014080
val.ret: 0xc000014080

      d: [201 2 3]

*/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文