《Go语言编程》学习总结2

参考书:Go语言编程

第二章  顺序编程


1 变量声明使用关键字var ,如下

    var v1 int

    var v2 string

    var v3  [10]int         //数组

    var v4 []int             //数组切片

    var v5  struct {

            f  int 

    }

    var v6  *int           //指针

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

    var v8  func(a int) int

2 var可以将若干个同样需要声明的同种类型的变量放在一起,如下

    var (

            v1  int

            v2  string

    )

3 变量初始化

    var v1 int  =  10

    var v2  =  10     // 编译器根据赋值自动定义变量类型

    v2 :=  10  

 4 用“:=”初始化变量时,左侧的变量必须是未声明过的变量,否则会导致编译错误

 5 Go语言支持多重赋值,如下

        i , j = j , i

6 Go语言支持匿名变量为了避免不会因为返回多个值的函数来定义一堆不需要的变量,如下

        func GetName( ) ( firstName , lastName , nickName string) {

                return "May" , "Chan" , "Chibi" 

        }

        _ , _ , nickName := GetName( )

7 常量定义

        const Pi float64 = 3.1415926535

        const zero = 0.0

        const (

                size int64 = 1024

                eof = -1

        )

        const u , v  float32 = 0 , 3

        const a , b , c = 3, 5.0 , "foo"      // a = 3 , b = 5.0 , c = "foo"

8 常量定义的右值也可以是一个在编译期运算的常量表达式,如下

        const  mask  =  1 << 3      // ok 

         const Home = os.GetEnv("HOME")     //error , 因为os.GetEnv()只有在运行期才能知道返回结果,在编译期并不能确定

9 Go语言预定义了这些常量:true ,false和iota

10 在每一个const关键字出现时被重置为0,然后在下一个const出现之前,每出现一次iota,其所代表的数字会自动增1,如下

            const (               // iota重置为0

                    c0 = iota    // c0 = 1

                    c1 = iota    //  c1 = 2

                    c2 = iota    //  c2 = 3

            )

            const x = iota     // x = 0

11 Go语言不支持enum关键字,Go常用const来实现枚举,如下

        const (

                Sunday = iota

                Monday

                Tuesday

                Wednesday

                Thursday

                Friday

                Saturday

                Sunday

         )

12 Go的基础类型,布尔类型(bool) ,整型(int8 , byte , int16 , int , uint , uintptr等) , 浮点类型(float32 , float64),复数类型(complex64 , complex128),字符串(string),字符类型(rune),错误类型(error),指针(pointer),数组(array),切片(slice),字典(map),通道(chan),结构体(struct),接口(interface)

13 布尔类型不能接受其他类型的赋值,也不支持自动或强制类型转换,如下

        var  b  bool

        b = true

        c := (1 == 2) 

        b = 1    // 编译错误

        b = bool(1)   // 编译错误

14 整型

  • int8        一个字节        -128 ~ 127
  • uint8        一个字节        0 ~ 255
  • int16        二个字节        -32768 ~ 32767
  • uint16        二个字节        0 ~ 65535
  • int32        四个字节        -2147483648 ~ 2147483647
  • uint32        四个字节        0 ~ 4294967295
  • int64        八个字节     
  • uint64
  • int
  • uint
  • uintptr

注:int和int32在Go语言里是被认为两种不同的类型,编译器是不会帮助做类型转换的

var value1 int32
value2 := 64     //  value2被自动推导为int类型
value1 = value2   // cannot use value2 (type int) as type int32 in assignment
    value1 = int32(value2)    // ok

15 两个不同类型的整型数不能直接比较,比如int8类型的数和int类型的数不能直接比较

16 Go语言定义了两个类型float32和float64,float32相当于C语言的float,float64相当于C语言的double

        fvalue :=  12.0    // 默认推导为float64

17 因为浮点数不是精确的表达方式,直接用==来判断两个浮点数是否相等会有风险

18 复数

        var value1  complex64

        value1 = 3.2+12i

        value2 := 1 + 3i

        value3 := complex(3.2 , 12)       // value3 := 3.2 + 12i

19 字符串

        var str string

        str = "Hello world"

        ch := str[0]

20 字符串操作

        x + y        字符串拼接        "Hello" + "123"    // "Hello123"

        len(s)        字符串长度        len("hello")     // 5

        s[i]        取字符            "Hello"[0]         // 'H'

21 字符串遍历,Go语言支持两种方式遍历字符串,如下

  • 字节数组的方式遍历  

        str := "Hello,world"

        n := len(str)

        for i := 0 ; i < n ; i++ {

                ch := str[i]                  // ch的类型为byte

                fmt.Println(i , ch)

        }

  • 以Unicode字符遍历

        str := "Hello,world"

        for i , ch := range str {

                fmt.Println(i , ch)         // ch的类型为rune

        }

注:Go语言支持两种字符类型,一个是byte,代表UTF-8字符串的单个字节的值,另一个是rune,代表单个Unicode字符。

22 数组的声明方式

  • [32]byte
  • [2*N] struct { x , y int32 }       // 复杂类型数组
  • [1000] *float64
  • [3][5] int
  • [2][2][2] float64

数组长度在定义后就不可更改,在声明时长度可以是常数也可以是变量。长度可以通过len( )函数获取

23 访问数组除了下标访问,可以使用关键字range,range会返回2个值,元素的数组下标和元素的值

        for i , v := range array {

                fmt.Println("Array element[" , i , "] = " , v)

        }

24 在Go语言中数组是一个值类型,不是引用类型,在赋值或参数传递时都会生成一个副本,修改不会改变原始数组。        

func main(){
   array := [5]int{1,2,3,4,5}
   array2 := array
   array2[2] = 4

   modify(array)
   fmt.Println("In main(), array values: ",array)
   fmt.Println("In main(), array2 values: ",array2)
}

func modify(array [5]int){
   array[0] = 10
   fmt.Println("In modify(), array values: ",array)
}
输出结果
In modify(), array values:  [10 2 3 4 5]
In main(), array values:  [1 2 3 4 5]
In main(), array2 values:  [1 2 4 4 5]


25 创建数组切片的方法主要有两种 --- 基于数组和直接创建

  • 基于数组创建

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

        var mySlice []int = myArray[:5]   

  • 使用内置函数make( )创建数组切片

        mySlice1 :=  make([]int , 5)       // 创建元素个数为5,元素值都为0的数组切片

        mySlice2 :=  make([]int , 5 , 10)     // 创建元素个数为5,元素值都为0,实际预留10个元素的存储空间。len(mySlice2)是5

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

26 数组切片较数组多了一个存储能力

        mySlice :=  make([]int , 5 , 10)

        fmt.Println("len(mySlice): " , len(mySlice))       //  5,即元素个数

        fmt.Println("cap(mySlice): " , cap(mySlice))     //   10 即数组切片分配的空间大小

27 数组切片新增元素可以使用append( ),如下

  • mySlice = append(mySlice , 1 , 2 , 3)     // 在切片尾新增3个元素1,2,3
  • mySlice2 := []int { 8 , 7 , 9 }

      mySlice  =  append(mySlice , mySlice2 . . . )       // 后面必须有省略号,表示将mySlice2的所有元素都传入

28 基于数组切片创建数组切片

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

        newSlice := oldSlice[ : 3]

29 数组切片内容复制,如下

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

        slice2 :=  []int { 5 , 4 , 3 }

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

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

30 map

        myMap := make(map[string] int)     // 创建map

        myMap := make(map[string] int , 100)    // 创建一个初始存储能力为100的map

        myMap := map[string] int {         // 创建并初始化

                "abc":123 ,

                "bcd":333 ,

        }

        delete( myMap , "abc")     // 删除某个key值的元素

31 map查找

        value , ok :=  myMap["abc"]      //查找会返回两个值,ok表示是否有这个元素

        if  ok  {

                    // toDo

         }

32 Go语言支持如下几种流程控制语句,还有break,continue和fallthrough

  • 条件语句,关键字为if ,else 和else if
  • 选择语句,关键字为switch,case和select
  • 循环语句,关键字为for和range
  • 跳转语句,关键字为goto

33 if语句,如下

        if  a < 5 {           // 条件语句不用加小括号(),大括号{ }一定要有

                return 0

        } else {

                return 1

        }

34 switch语句,如下       

i := 1
switch i {      // 左大括号{一定要和switch同一行
case 0:
   fmt.Println(0)    // 不需要用break来声明退出case
case 1:
   fmt.Println(1)
case 2:
   fallthrough      // fallthrough表示继续执行紧跟的下一个case
case 3:
   fmt.Println(3)
case 4, 5, 6:       //  单个case中可以出现多个结果选项
   fmt.Println("4,5,6")
default:
   fmt.Println("default")
}
switch{            //  可以不设定switch之后的条件表达式,只写一个switch
case 0<=i && i < 1:    // 条件表达式可以不只限制为常量或整数
   fmt.Println(0)
case 1<=i && i < 2:
   fmt.Println(1)
}

35 Go语言循环语句只支持for,不支持while和do-while

        for  i := 0 ; i < 10 ; i ++ {     // 条件语句不用加小括号( )

                fmt.Println(i)

        }

        sum := 0

        for {

                sum ++

                if sum > 100 {

                        break

                }

        }

        a := []int{1,2,3,4,5,6,7}

        for i , j := 0 , len(a) - 1 ; i < j ; i , j = i+1 , j-1 {

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

        }

36 Go语言的for循环支持continue和break来控制循环

37 跳转语句

        func myfunc( ) {

                i :=  0

                HERE :

                        fmt.Println(i)

                        i++

                        if i < 10 {

                                goto HERE

                        }

        }

38 函数定义

            func  Add(a int , b int) (ret  int , err error)

            func  Add(a , b int) int 

39 函数调用,先导入该函数所在的包,调用即可,如下

            import "mymath"      // 假设Add被放在一个叫mymath的包中

            c := mymath.Add(1 , 2)

40 Go语言有这样的规则,小写字母开头的函数只能在本包内可见,即为private,大写字母开头的函数才能被其他包使用,即public

41 不定参数

        func myfunc( args . . . int ) {   // 该函数可以接受不定数量的参数,并且这些参数类型都是int

                for _ , arg := range args {

                        fmt.Println(arg)

                }

        }

        myfunc(2 , 3)     // ok

        myfunc(1, 2, 3)   //  ok

42 不定参数的传递

        func myfunc( args . . . int) {

                myfunc3(args . . . )      // 不定参数的传递必须在后面加上省略号

                myfunc3(args[1 : ] . . . )    // 不定参数的传递必须在后面加上省略号

        }

43 任意类型的不定参数,使用interface{ }

        func Printf(format string , args . . . interface{ })

44 函数的一个实例

func MyPrintf(args ...interface{}){
   for _,arg:= range args{
      switch arg.(type){
      case int:
         fmt.Println(arg," is an int value")
      case string:
         fmt.Println(arg, " is a string value")
      case int64:
         fmt.Println(arg, " is an int64 value")
      default:
         fmt.Println(arg, " is an unknown type")
      }
   }
}

func main(){
   var v1 int = 1
   var v2 int64 = 234
   var v3 string = "hello"
   var v4 float32 = 1.234
   MyPrintf(v1,v2,v3,v4)
}

输出结果:

1  is an int value
234  is an int64 value
hello  is a string value
1.234  is an unknown type

45 匿名函数由一个不带函数名的函数声明和函数体组成,可以直接赋值给一个变量或直接执行

         f := func (a , b int , z float64 ) bool  {    // 没有函数名,直接给变量f赋值

                    return a * b < int(z)

         }

         func ( ch chan int ) {

                ch <- ACK    

        }  (reply_chan)     // 函数后带括号即直接执行,将reply_chan值传入函数中

47 error接口,定义如下

            type error interface {

                    Error() string

            }

48 一个函数可以有多个defer语句。defer语句调用顺序为先进后出,最后一个defer语句先执行

49 当函数执行过程中调用panic( ),正常的函数执行流程将立即终止。recover( )用于终止错误处理流程





猜你喜欢

转载自blog.csdn.net/haima95/article/details/80818350
今日推荐