二:类型、定义函数、返回值以及package别名和省略调用
一:类型、定义函数、返回值
内容:(1):数据类型了解下
(2):字符串怎么定义?怎么使用?
(3):如何定义函数?
(4):同文件中函数怎么调用?怎么带参数?怎么带返回值?
(5):如何注释代码?如何定义变量?
(1):数据类型
(a):基本类型(数字,字符串,布尔类型)
(b):复合类型(数组<Array>,结构<struct>)
(c):引用类型(指针,切片,函数,通道)
(d):接口类型

二:先看个比较简单的“字符串”

三:Go string 实现原理剖析
(1):先看底层对string注释(string的标准结构)
Go标准库builtin给出了所有内置类型的定义,源代码位于src/builtin/builtin.go,其中关于string的描述如下:

string是所有8位字节字符串的集合,通常是这样,但并不一定是表示utf -8编码的文本。
另外,还提到了两点,非常重要:
(a):string可以为空(长度为0),但不会是nil;
(b):string对象不可以修改;
(2):string 的数据结构
源码包src/runtime/string.go
stringStruct定义了string的数据结构:

注释:string数据结构跟切片有些类似,只不过切片还有一个表示容量的成员,事实上string和切片,准确的说是byte切片经常发生转换。这个后面再详细介绍
(3):string操作
字符串构建过程是先跟据字符串构建stringStruct,再转换成string。转换的源码如下: src/runtime/string.go

string在runtime包中就是stringStruct,对外呈现叫做string。
(4):[]byte转string
byte切片可以很方便的转换成string,如下所示:

需要注意的是这种转换需要一次内存拷贝
转换过程如下:
(1):跟据切片的长度申请内存空间,假设内存地址为p,切片长度为len(b);
(2):构建string(string.str = p;string.len = len;)
(3):拷贝数据(切片中数据拷贝到新申请的内存空间)

(5):string转[]byte
string也可以方便的转成byte切片,如下所示:

string转换成byte切片,也需要一次内存拷贝,其过程如下:
(1):申请切片内存空间
(2):将string拷贝到切片

(6):字符串拼接
字符串可以很方便的拼接,像下面这样:
str := "Str1" + "Str2" + "Str3"
即便有非常多的字符串需要拼接,性能上也有比较好的保证,因为新字符串的内存空间是一次分配完成的,所以性能消耗主要在拷贝数据上。
(7):为什么字符串不允许修改?
像C++语言中的string,其本身拥有内存空间,修改string是支持的。但Go的实现中,string不包含内存空间,只有一个内存的指针,这样做的好处是string变得非常轻量,可以很方便的行传递而不用担心内存拷贝。
因为string通常指向字符串字面量,而字符串字面量存储位置是只读段,而不是堆或栈上,所以才有了string不可修改的约定。
(8):string和[]byte如何取舍
string和[]byte都可以表示字符串,但因数据结构不同,其衍生出来的方法也不同,要跟据实际应用场景来选择。
string 擅长的场景:
(1):需要字符串比较的场景;
(2):不需要nil字符串的场景;
[]byte擅长的场景:
(1):修改字符串的场景,尤其是修改粒度为1个字节;
(2):函数返回值,需要用nil表示含义的场景;
(3):需要切片操作的场景;
总结:虽然看起来string适用的场景不如[]byte多,但因为string直观,在实际应用中还是大量存在,在偏底层的实现中[]byte使用更多。
四:别名使用
当使用第三方包时,包名可能会非常接近或者相同,此时就可以使用,别名来进行区别和调用
eg:
import std "ftm"
或
import(
std "ftm"
)
调用时候就需要使用别名替换
func main(){
std.Println("Hello World!")
}
五:省略调用
eg:
import . "fmt"
或
import(
. "fmt"
)
调用时候省略包名
func main() {
Println("Hello World!")
}
注意:
(1):省略调用不建议使用,易混淆,时间久了就不知道函数属于哪个包了;
(2):省略调用不可以和别名同时使用
六 函数的定义


浙公网安备 33010602011771号