美文网首页
许世伟的Go语言基础 第二章总结

许世伟的Go语言基础 第二章总结

作者: fjxCode | 来源:发表于2018-07-16 20:20 被阅读0次

    第2章 顺序编程

    2.1 变量

    变量声明

    变量声明的类型信息放在变量之后,放在数组的中括号之后,作返回值类型放在方法名之后。

    不需要使用分号作为结束符。

    //字串和哈希表都是内置类型,都小写

    varv1int

    varv2string

    varv3[10]int

    varv4[]int//数组切片

    v4=make([]string,10)

    varv5stuct{

    fint

    }

    varv6*int

    varv7map[string]int//map,key为string类型,value为int类型

    varv8func(aint)int

    Go语言是个静态类型语言,但以上写法看上去却像动态语言。

    var只用来声明,直接不值不用写var。

    varv1=1//编译器报错

    go语言变量赋值不使用也报错。

    变量初始化

    注意类型推演符左侧的就是不应该是已被声明过的。

    varv1int=10

    varv2=10//不指明类型也可以变量推演

    varv3:=10//使用类型推演符:=

    ==总结==:没声明的必须类型推演,只声明没指定类型的可以类型推演,已声明类型的不能类型推演。

    不用类型推演:=,用变量必须声明var,可以不写类型。

    交换2个变量的值直接用多重赋值

    i,j=j,i

    匿名变量

    可以使用多重返回和匿名变量的写法,使代码更优雅。

    funcmain() {

        _,_,nickName:=GetName()

    }

    //多个同样类型的变量只声明一次就可以

    funcGetName() (firstName,lastName,nickNamestring)  {

        return"May","Chan","Maruko"

    }

    字面常量

    Go语言的字面常量是无类型的,只要值在某类型的值域范围内,就可以赋值(不用再写类型转换了,简化代码)。如-12可以赋给int、unit、int32、float64等。

    -12

    3.14159//浮点型常量

    3.2+12i//复数常量

    true//布尔型常量

    "foo"//字串常量

    常量定义

    常量也可以限定类型,但不是必须的。

    constzerofloat64=3.14159

    constzero=3.14159// 无类型常量

    const{

    zeroint64=0

    zero=0//无类型常量

    }

    ==常量赋值是编译期行为==,常量定义的右侧值也可以是一个编译期运行的常量表达式。

    constmask=1<<3

    //os.GetEnv("HOME")是运行期返回结果,所以下行代码编译错误

    constHome=os.GetEnv("HOME")

    预定义常量

    go语言有3个预定义常量:true、false、iota。

    每const关键字出现时,iota被重置为0,每出现一次iota其值增1。

    const{

    c0=iota

    c1=iota

    c2=iota

    }

    两个const赋值表达式是一样的,则可以省略后一个(==方便之处在于枚举型赋值,但可能带来意外赋值==)。这种写法多用于枚举型。

    const{

    a=1<

    b//b == 2

    c//c == 4

    }

    枚举

    go语言并不支持enum关键字。枚举使用const后跟一对==圆括号==定义一组常量。

    const(

    Sunday=iota

    Monay

    TuesDay

    numberOfDays//这个常量没有导出

    )

    go语言中大写字母的常量在包外可见,相当于访问限制符。

    2.3 类型

    go语言内置以下基础类型(7个)

    bool

    byte int unit int8 int16 uint uintptr等。(整形一般用int unit就可以了,以免移植困难)

    float32 float64

    complex64 complex128

    string

    字符类型rune

    错误类型error

    go语言的复合类型(7个)

    指针pointer

    数组array

    切片slice

    字典map

    通道chan

    结构体struct

    接口interface

    布尔型

    varv1bool=true

    布尔型不接受其它类型的赋值,也不支持强制类型转换。

    整形

    int和int32是两种不同的类型,编译器不会自动转换。

    value1:=64//自动推导为

    varvalue2int32

    value2=value1//编译器报错

    go语言不会隐式的类型转换,不同类型的整型不能比较和赋值,如int8和int。但可以直接与字面值常量比较(无类型)。(没有隐式类型转换的烦恼)

    不同类型赋值要强制类型转换

    value2=int32(value1)//强制转换用静态方法

    variint32

    varjint64

    i,j=1,2

    ifi==j{}//编译器报错

    ifi==1||j==2{}//编译通过

    ==取反运算符是^x==,这与C语言不同。

    浮点型

    varfvalue1

    fvalue1:=12.0//加小数点,推导为浮点型。

    float32等价于C语言中的float型,float64等价于C语言中的double型(浮点型自动推演的的类型)。

    用==比较浮点型不稳定,使用以下方案:

    import"math"

    funcIsEqual(f1,f2,pfloat64){

    returnmath.Fdim(f1,f2)

    }

    复数

    复数表示

    varvaluecomplex64

    value1=3.2+12i

    value2:=complex(3.2,12)

    real(value1)//取实部

    imag(value1)//取虚部

    字串

    varstrstring

    str="hello"

    ch:=str[0]

    fmt.Printf("the length of \"%s\" is %d \n",str,len(str))

    fmt.Printf("the first character of \"%s\" is %c"str,ch)

    字串不能在初始化后修改

    str:="hello"

    str[0]"X"//编译错误

    字串编码转换go只支持utf-8和unicode。其它可用iconv库转换。

    字串操作:

    x+y//字串连接

    len(s)//取字串长度

    s[i]//取字符

    //两种字串遍历方式

    str:="hello"

    n:=len(str)

    fori,ch:=rangestr{

    fmt.Println(i,ch)

    }

    fori:=0;i

    ch:=str[i]

    fmt.Println(i,ch)//可以直接打印两个字符

    }

    字符

    两种字符类型,byte表示UTF-8字串的单个字节值,rune代表单个Unicode字符。

    数组

    数组声明方法:

    [32]byte

    [2*N]struct{x,yint}//复杂类型数组

    [1000]*float指针类型数组

    [3][5]int//二维数组

    [2][2][2]float64//等同于[2]([2]([2]float64))

    varfVar[2][2]float64=[2][2]float64{{1,2},{1,2}}

    数组可以是多维的,一旦定义长度后就不能修改。

    go语言是值类型,在赋值和参数传递时会进行一次复制动作。因而在函数体中无法修改数组的内容,函数内操作的只是所传入数组的一个副本。

    数组切片

    数组在长度定义后无法修改,数组是值类型,这些无法满足开发者需求。

    数组切片的数据结构可以抽象为以下3个变量:(类似于ArrayList)

    指向原生数组的指针

    数组切片的元素个数

    数组切片已分配的存储空间

    vararray1[10]int=[10]int{1,2,3,4,5,6,7,8,9,10}

    varslice1[]int=array1[:5]//使用数组的片段创建切片

    slice2=make([]int,5)//创建元素个数为5的数组切片

    slice3=make([]int,10)//创建元素个数5的数组切片,预留10个存储空间

    slice4:=[]int{1,2,3,4,5}//直接创建5个元素的数组切片

    len(slice1)

    cap(slice1)//返回容量大小

    这里书中有误:==make方法返回值==赋变量 ,无需类型推演。

    ==让编译器自行统计元素个数==:

    b := [...]string{"Penn", "Teller"}

    切片能够区分元素个数和容量。为避免扩容开销,容量由开发人员指定。

    slice1:=append(slice1,8,9,10)//向切片末尾添加元素

    slice1:=append(slice1,slice2)//添加切片

    使用切片创建切片:

    newSlice:=oldSlice[:3]//选择范围超过原切片,则补上0

    切片复制:

    slice1:=[]int{1,2,3,4,5}

    slice2:=[]int(5,4,3)

    copy(slice2,slice1)//只复制slice1的前3个元素到slice2中

    copy(slice1,slice2)//复制slice2的元素到slice1的前3个位置

    切片复制的原则是==不改变原切片长度==。

    map

    varmap1map[int]string

    map1=make(map[int]string)

    map1[1]="jack"

    map1[2]="bill"

    str,ok=map1[1]//查找键为1的数据

    map的多返回值判断是否查找成功,使代码更简洁。

    map初始化时可以设置容量:

    map1=make(map[int]string,100)

    添加元素如同元素赋值。

    删除元素:

    delete(map1,1)

    struct(引自博客)

    //结构体初始化

    b := person{

           name: "wyff",

           age:  300,

       }

    2.4 流程控制

    选择语句支持switch、case和select。循环语句支持for和rage。跳转语句支持goto。

    if语句要求

    不需要括号()包条件

    无论几条语句,{}是必须的

    左花括号必须与if/else在同一行

    有返回值函数中,不允许将"最终"return放在if...else中。

    if语句也可以在条件表达式前加赋值语句。

    switch选择语句

        switchi{

        case0:

            fmt.Print("0")

        case1:

            fmt.Print("1")

        case2:

            fmt.Print("2")

        default:

            fmt.Print("default")

        }

    switch后无表达式的写法:

        varNum

        switch{

        case0

            fmt.Print("0-3")

        case4

            fmt.Print("4-6")

        }

    //case不再是匹配项,而是表达式。

    要求:

    左花括号必须与switch处于同一行

    条件表达式==不限制不整形或常量==,也可以不写

    单个case可以出现多结果选项??

    ==不需要break来明确退出一个case==,只有加fallthrough关键字才继续执行下一个case。

    switch后无表达式,与if...else逻辑等同。

    循环语句

    无限循还直接写,而不需要for(;;)和do{}while(1)

    for{

    }

    条件表达式支持多重赋值:

    foti,j=0,len(arr);i

    a[i],a[j]=a[j],a[i]

    }

    支持continue break循环控制,还可以决定跳出哪个循还。

    forj:=0;j<5;j++{

    fori:=0;i<5;i++{

    ifi>3{

    breakJLoop

       }

    fmt.

      }

    }

    JLoop://循环标签

    ==注意循还标签有冒号==。Java使用bool标志来实现。

    跳转语句

    HERE:

    ifi<10{

    gotoHERE

    }

    2.5 函数

    相邻的类型相同的参数,可以只写一个类型声明

    函数的返回值的变量需要命名,只有一个可以不命名

    funcAdd(a,bint)(resint,errerror){

    err=errors.New("have errors")

    return

    }

    forAdd(a,bint)int{}//单个返回值

    func(a*Integer)Add(i,jint)int{returnx+y}//类方法的写法,是否加*后面讲

    函数和变量的小写仅在包内可见,大写才能被其它包使用。相当于访问限制符。

    多返回值

    匿名函数和闭包

    匿名函数可以直接赋值给一个变量或直接执行。

    f:=func(x,yint)int{

    returnx+y

    }

    f:=func(x,yint)int{

    returnx+y

    }(1,2)//后面带参数表示直接执行

    匿名函数是一个闭包。

    闭包定义:包含自由变量(未绑定到对象)的代码块。要执行的代码块为自由变量提供绑定的计算环境(作用域)。

    闭包的价值:用作函数对象或匿名函数,==支持闭包的语言将函数存储到变量作为参数传递给其它函数==。

    闭包是函数式编程中很重要的概念。

    funcmain() {

        varjint=5

        a:=func() (func()){

            variint=10

            returnfunc() {fmt.Printf("i,j:%d,%d",i,j)}

        }()

        a()

        j*=2

        a()

    }

    //闭包内的i值被隔离,不会被修改。

    //fmt.Print()用法如java,fmt.Printf()用法如C。

    错误处理

    typeerrorinterface{

    Error()string

    }

    将error作为多返回值的最后一个,用于函数的返回错误。

    错误处理:

    iferr!=nil{}

    defer关键字

    提前写关闭文件、连接的语句。java用finally,C++用包一个类在析构函数中关闭。

    funcCopyFile(dst,srcstring) (wint64,errerror) {

        srcFile,err:=os.Open(src)

        iferr!=nil{

            return

        }

        defersrcFile.Close()

        dstFile,err:=os.Create(dst)

        iferr!=nil{

            return

        }

        deferdstFile.Close()

        returnio.Copy(dstFile,srcFile)

    }

    panic()和recover()方法

    错误处理流程:

    当一个函数调用panic()函数时,正常的函数执行流程立即终止。

    但使用defer关键字推迟执行语句正常展开执行。

    函数返回到调用函数,逐层执行panic流程,直至所属的goroutine中所有执行的函数被终止。

    报告错误信息,包括panic()函数传入的参数。

    panic()的形参接收任意类型的数据。

    recover()函数终止错误处理流程:如果没有在没有发生异常的goroutine中明确地调用恢复过程(使用recover()),则goroutine所属的进程==打印异常信息==后直接退出。

    相关文章

      网友评论

          本文标题:许世伟的Go语言基础 第二章总结

          本文链接:https://www.haomeiwen.com/subject/djqipftx.html