Chinaunix首页 | 论坛 | 博客
  • 博客访问: 287937
  • 博文数量: 124
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 21
  • 用 户 组: 普通用户
  • 注册时间: 2016-08-20 14:44
文章分类

全部博文(124)

文章存档

2020年(1)

2018年(2)

2016年(2)

2015年(6)

2014年(10)

2013年(23)

2012年(7)

2011年(18)

2010年(15)

2009年(8)

2007年(8)

2006年(23)

2005年(1)

我的朋友

分类: C/C++

2013-06-22 11:34:58

五, Array 与 slice

数组是固定长度的,slice是长度可以变的。但是slice是寄生在array上的。

数组的赋值为有以下几种写法,但是无论那种,右边的长度在编译时都是已知的。左边则是明确写出,或者由编译器自动识别;
var b[2]int=[2]int{11,12} //此时b是固定长度位2的数组。
var c[2]int=[...]int{11,12} //同上。
var d=[...]int{1,2,3,4}
e:=
[...]int{1,2,3,4}

go的数组与C的数组相同,都是一段编译时就计算好的空间;所以不支持动态长度;
如:
var i[10] int; //此处已经有了10个int的空间已经分配; 和c相同,和java不同;
i=[10]int{1,2,3,4,5,6,7,8,9,0}; //此处的复制就是将后面的数组里面的内容拷贝到i所在的空间中去; 此处是不是还有一个匿名数组还不知道;c中是不支持这样的赋值的;
i=[10]int{1,2}//总共是10个,只写了2个,其他都自动填充0;



slice是寄生于array的;其写法为:
var s=d[1:2],  //表示s是从第一个元素开始,第二个元素结束(不包括2)
var s1=d[:],    //表示s1是d的全部
var s2=d[:2],  //表示s2是0开始,2结束
var s3=d[1:], //表示从1开始到最后

一不小心突然发现有了一个新写法
var a []int = [] int{1,2};以为发现了一种新的数组赋值方法。这里的a实际是slice;此时这个数组是匿名的了。

下面的代码输出位:
[1/2]0x7f71d56d5f4c &a=0x7f71d56d5f48 a=1 2 4 [1/1]0x7f71d56d5f54

点击(此处)折叠或打开

  1. var a = [...]int32{1, 2, 4}
  2.     var b = a[1:2]
  3.     print(b)
  4.     b = []int32{10}
  5.     print("&a=", &a, " a=")
  6.     for i := 0; i < len(a); i++ {
  7.         print(a[i], "\t")
  8.     }
  9.     print(b)
  10.     println()

  1. 可以见到在4行赋值前后,prinf出来的b的值变了,这是因为此处打印的实际是该slice对应的数组的起始位置;
  2. 如果代码中多出打印&b的值,就会发现&b是不会变化的;
  3. 实际在golang中(通过gdb汇编代码可以看到),golang中的数组对应于实际c中的数组,指示预留空间比代码中要求的要大;可以在gdb中用sizeof(a)看到;golang可以判断对数组的访问是否越界,这是通过在每次访问下标前添加汇编代码判断达到的。这也是为什么数组的定义必须明确写出长度的原因;
  4. 与数组相比, slice则而外多了一个结构体,其中有三个域,分别为:指向该slice实际存储区域的指针,当前slice的长度(len),和当前slice的容量(cap);

六,len注意点:

len(string)返回的是该字符串所占用的字节数,而不是字符的个数。 由于都是utf-8,中文字符的长度超过了2, 所以总结果是13;

点击(此处)折叠或打开

  1. package main
  2. func main() {
  3. var s="Hello, 世界"
  4.     println(len(s))
  5. }
对于s,用c语言来描述是一个结构体,其中包含了两个元素(str (*uint8), len(int64));其中str指向了真正的字符串;len中记录了字符串的长度;

所以,只有array的长度是直接由编译器得到,而slice,和string的长度则是有变量记录的;

七, 指针

在golang中是有指针的,这一点给程序员带来了很大的方便,java没有提供求地址的功能,很是不便;比如下面的modify函数,如果在java中如果需要得到一个新的string值,只能通过返回值返回了。如果此时又有需求返回一个其他的返回值,就没有办法了;

点击(此处)折叠或打开

  1. package main
  2. func modify(a * string){
  3.         *a="hi"
  4. }
  5. func mo(b string){
  6.         b="compy"
  7. }
  8. func main(){
  9.         var s string="hello"
  10.         println(s)
  11.         mo(s)
  12.         println(s)
  13.         modify(&s)
  14.         println(s)
  15. }
通过上面的程序可以发现,modify函数传进去的是s的地址,所以等函数返回后,s所对应的字符串已经更改;而mo函数中的b由于是s的copy,所以虽然在函数中修改了b的值,但是等函数返回后,仍没有效果, 但是有一点需要注意的是,b这个copy中,指示上面的str,len两个变量拷贝了,而实际的字符串只有一份,所以节约了空间,提供了性能;

写这段代码的时候,发现一个细节问题,如果注释掉行13; 在gdb中调试到第10行是,可以使用p s命令和whatis s命令查看s的具体结构,但是如果留有13行,则symble table中的变量变成了&s,在gdb中可以使用i locals查看到该变量,但是如果用p打印该变量,还有待研究。


阅读(4221) | 评论(0) | 转发(0) |
0

上一篇:学习golang 入门

下一篇:golang package

给主人留下些什么吧!~~