二:类型、定义函数、返回值以及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):省略调用不可以和别名同时使用

六 函数的定义

  

   

 

posted @ 2020-04-22 08:59  痞子胥  阅读(236)  评论(0)    收藏  举报