Go基础学习

Go基础学习

  1. go的基础语法

    fmt.Println("hello world!") //go采用行分隔符
    
    关键字
    下面列举了 Go 代码中会使用到的 25 个关键字或保留字:
    
    break	default	func	interface	select
    case	defer	go	map	struct
    chan	else	goto	package	switch
    const	fallthrough	if	range	type
    continue	for	import	return	var
    除了以上介绍的这些关键字,Go 语言还有 36 个预定义标识符:
    
    append	bool	byte	cap	close	complex	complex64	complex128	uint16
    copy	false	float32	float64	imag	int	int8	int16	uint32
    int32	int64	iota	len	make	new	nil	panic	uint64
    print	println	real	recover	string	true	uint	uint8	uintptr
    程序一般由关键字、常量、变量、运算符、类型和函数组成。
    程序中可能会使用到这些分隔符:括号 (),中括号 [] 和大括号 {}。
    程序中可能会使用到这些标点符号:.、,、;、: 和 …。
    
    go的变量声明必须以空格隔开
    例如: var name string
    
  2. go的数据类型

    //数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存。
    
    Go 语言按类别有以下几种数据类型:布尔类型,数字类型,字符串类型,派生类型四种。
    
    派生类型有:指针类型(Pointer),数组类型,结构化类型(struct),Channel 类型,函数类型,切片类型,接口类型(interface), Map 类型
    
    数字类型
    Go 也有基于架构的类型,例如:int、uint 和 uintptr。
    uint8:无符号 8 位整型 (0 到 255)
    uint16:16 位整型 (0 到 65535)
    uint32:32 位整型 (0 到 4294967295)
    uint64:无符号 64 位整型 (0 到 18446744073709551615)
    int8:有符号 8 位整型 (-128 到 127)
    int16:有符号 16 位整型 (-32768 到 32767)
    int32:有符号 32 位整型 (-2147483648 到 2147483647)
    int64:有符号 64 位整型 (-9223372036854775808 到 9223372036854775807)
    
    浮点型
    
    float32:IEEE-754 32位浮点型数
    float64:IEEE-754 64位浮点型数
    complex64:32 位实数和虚数
    complex128:64 位实数和虚数
    
    其他数字类型
    byte:类似 uint8
    rune:类似 int32
    uint:32 或 64 位
    int:与 uint 一样大小
    uintptr:无符号整型,用于存放一个指针
    
  3. go的变量

//Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字
第一种,使用var 变量名 变量类型的形式声明变量
var myvar int//一次性可以声明多个变量,var myvar,youvar int
第二种,自定推断变量类型
var myvar = 100 //自动识别为int型
第三种,省略var 声明的变量,注意 := 左侧如果没有声明新的变量,就产生编译错误
myvar := "hello world"

多变量声明
//类型相同多个变量, 非全局变量
var vname1, vname2, vname3 type
vname1, vname2, vname3 = v1, v2, v3
var vname1, vname2, vname3 = v1, v2, v3 // 和 python 很像,不需要显示声明类型,自动推断

// 这种因式分解关键字的写法一般用于声明全局变量
var (
    vname1 v_type1
    vname2 v_type2
)

使用:=赋值操作符
myvar := 100  //编译器自动推断类型,但是这种写法只能用在函数体内
如果想要改变myvar的值的话必须使用myvar=10,而不能再次使用myvar := 10

var a,b = 10,20
如果想要交换两个数的值var a,b = b,a

空白标识符 _ 被用于抛弃值,如值 5 在:_, b = 5, 7 中被抛弃。
_ 实际上是一个只写变量,你不能得到它的值。这样做是因为 Go 语言中你必须使用所有被声明的变量,但有时你并不需要使用从一个函数得到的所有返回值。
  1. go 常量

    /*常量是一个简单值的标识符,在程序运行时,不会被修改的量。
    常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。*/
    const identifier [type] = value
    显式类型定义: const b string = "abc"
    隐式类型定义: const b = "abc"
    
    常量还可以用作枚举:
    const (
        Unknown = 0
        Female = 1
        Male = 2
    )
    常量可以用len(), cap(), unsafe.Sizeof()函数计算表达式的值。常量表达式中,函数必须是内置函数,否则编译不过。
    
    iota 特殊常量,可以认为是一个可以被编译器修改的常量。
    iota 在 const关键字出现时将被重置为 0 类似于id自加一
    也可以用作枚举:
    const {
        a=iota
        b
        c
    }
    表示a=0,b=1,c=2
    
  2. go运算符

Go 语言内置的运算符有:算术运算符,关系运算符,逻辑运算符,位运算符,赋值运算符,其他运算符。
其他的运算符都是比较简单的,
位运算符:位运算符对整数在内存中的二进制位进行操作。

下表列出了位运算符 &, |, 和 ^ 的计算:
p	q	p & q	p | q	p ^ q
0	0	0	0	0
0	1	0	1	1
1	1	1	1	0
1	0	0	1	1
&:表示全真则为真
|:表示一真则真
^:表示异或运算,相同为0,不同为1
<<:	左移运算符"<<"是双目运算符。左移n位就是乘以2的n次方。 例如:2<<3结果为16
>>	右移运算符">>"是双目运算符。右移n位就是除以2的n次方。 例如:16>>2 结果为4

其他运算符
&:返回变量存储地址 例如:&a; 将给出变量的实际地址。
*:指针变量。 例如:*a; 是一个指针变量
  1. go条件语句
if语句,if..else 和if嵌套语句
switch语句
switch var1 {
    case val1:
        ...
    case val2:
        ...
    default:
        ...
}
switch 默认情况下 case 最后自带 break 语句,匹配成功后就不会执行其他 case,如果我们需要执行后面的 case,可以使用 fallthrough,fallthrough会强制执行下一条语句
	a:=10
	switch a {
	case 10:
		fmt.Print(a)
		fallthrough
	case 20:
		fmt.Println("20")
	default:
		fmt.Println("haas")
	}
结果输出为 10 20

Type Switch
switch 语句还可以被用于 type-switch 来判断某个 interface 变量中实际存储的变量类型。
 var x interface{}
   switch i := x.(type) {
      case nil:   
         fmt.Printf(" x 的类型 :%T",i)                
      case int:   
         fmt.Printf("x 是 int 型")                       
      case float64:
         fmt.Printf("x 是 float64 型")           
      case func(int) float64:
         fmt.Printf("x 是 func(int) 型")                      
      case bool, string:
         fmt.Printf("x 是 bool 或 string 型" )       
      default:
         fmt.Printf("未知型")     
   }   

select语句
select语句:类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。

Go 编程语言中 select 语句的语法如下:
select {
    case communication clause  :
       statement(s);      
    case communication clause  :
       statement(s); 
    /* 你可以定义任意数量的 case */
    default : /* 可选 */
       statement(s);
}
select语句的用法:
1. 每个 case 都必须是一个通信
2. 所有 channel 表达式都会被求值
3. 所有被发送的表达式都会被求值
4. 如果任意某个通信可以进行,它就执行,其他被忽略。
5. 如果有多个 case 都可以运行,Select 会随机公平地选出一个执行。其他不会执行。 
	否则:
		如果有 default 子句,则执行该语句。
		如果没有 default 子句,select 将阻塞,直到某个通信可以运行;Go 不会重新对 channel 或值进行求值。
  1. go循环语句

    for循环
    
    和 C 语言的 for 一样:
    	for init; condition; post { }
    和 C 的 while 一样:
    	for condition { } //里面必须要有条件结束标志,不然就成了死循环了
    和 C 的 for(;;) 一样:
    	for { }	//无限循环
    init: 一般为赋值表达式,给控制变量赋初值;
    condition: 关系表达式或逻辑表达式,循环控制条件;
    post: 一般为赋值表达式,给控制变量增量或减量。
    
    for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环。格式如下:
    for key, value := range oldMap {
        newMap[key] = value
    }
    
    break,continue,goto
    

8.go函数

Go 语言函数定义格式如下:
func function_name( [parameter list] ) [return_types] {
   函数体
}
例如:两数交换
func Max(var1,var2 int) int {
	if var1>var2 {
		return var1
	}else {
		return  var2
	}
}

func main()  {
	a,b:=12,13
	max:= Max(a,b)
	fmt.Print(max)
}


go函数可以返回多个值:
func swap(x, y string) (string, string) {
   return y, x
}

func main() {
   a, b := swap("Google", "Runoob")
   fmt.Println(a, b)
}


传递类型	描述
值传递	值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
引用传递 引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
默认情况下,Go 语言使用的是值传递,即在调用过程中不会影响到实际参数。

将函数作为一个实参传递到一个函数
func main(){
   /* 声明函数变量 */
   getSquareRoot := func(x float64) float64 {
      return math.Sqrt(x)
   }

   /* 使用函数 */
   fmt.Println(getSquareRoot(9))
}
  1. go变量作用域

    go变量分为局部变量,全局变量,和参数形参
    局部变量和全局变量名称可以相同,但是局部变量会优先考虑,参数形参可以当做局部变量来使用
    
  2. go数组

    //一维数组的声明和初始化
    var balance [10] float32 //数组声明
    var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}//初始化
    //多维数组的声明和初始化
    var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type
    
    	var arra  = [3][2]int{{1,4},{2,5},{2,55}}//声明一个二维数组
    	for i:=0;i<3 ;i++  {
    		for j:=0;j<2 ;j++  {
    			fmt.Printf("array[%d][%d]:%d
    ",i,j,arra[i][j])//遍历输出数组内容
    		}
    	}
    //向函数传递数组
    //求平均值
    func getAverage(arr []int, size int) float32
    {
       var i int
       var avg, sum float32  
    
       for i = 0; i < size; ++i {
          sum += arr[i]
       }
        
       avg = sum / size
        
       return avg;
    }
    
  3. go指针

    指针指向了一个值的内存地址。获取一个变量的内存地址使用&,例如:&a返回的就是变量a在内存中的地址。
    
    var var_name *var-type
    var-type 为指针类型,var_name 为指针变量名,* 号用于指定变量是作为一个指针。
    
    指针使用流程:1.定义指针变量。2.为指针变量赋值。3.访问指针变量中指向地址的值。
    在指针类型前面加上 * 号(前缀)来获取指针所指向的内容。
    例如:
    var a = 10
    var point *int
    point=&a //存储的是变量a的内存地址
    如果直接输出point则输出的是内存地址,要输出地址中存储的值,需要*point即可。
    
    GO空指针
    当一个指针被定义后没有分配到任何变量时,它的值为 nil。即空指针。
    一个指针变量通常缩写为 ptr。
    需要进行指针判断
    if(ptr != nil)     /* ptr 不是空指针 */
    if(ptr == nil)    /* ptr 是空指针 */
    
    指针数组:即将数组的地址保存在一个指针数组中,需要的时候即可使用*ptr[i]获取到对应内存地址的值。
    
    指向指针的指针:
    var ptr **int	//指向指针的指针变量,如果要访问它的值需要使用**ptr 即可。
    
  4. go语言结构体

    //如下定义书的结构体
    type Books struct {
       title string
       author string
       subject string
       book_id int
    }
    
     // 创建一个新的结构体
        fmt.Println(Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407})
        // 也可以使用 key => value 格式
        fmt.Println(Books{title: "Go 语言", author: "www.runoob.com", subject: "Go 语言教程", book_id: 6495407})
        // 忽略的字段为 0 或 空
       fmt.Println(Books{title: "Go 语言", author: "www.runoob.com"})
    
    访问结构体成员:结构体.成员名
    var book1 Books //声明一个结构体变量
    book1.title="go 语言"
    fmt.println(book1.title)  //输出结构为:go 语言
    
    也可以将结构体变量作为函数参数:访问也是结构体变量名.结构体成员名。
    
    结构体指针:var struct_pointer *Books
    以上定义的指针变量可以存储结构体变量的地址。查看结构体变量地址,可以将 & 符号放置于结构体变量前:
    struct_pointer = &Book1;
    使用结构体指针访问结构体成员,使用 "." 操作符:
    struct_pointer.title;
    
  5. go语言切片

    Go 语言切片是对数组的抽象。也就是动态的数组,数组的长度不固定,可以动态的追加元素。
    var identifier []type //切片不需要说明长度。
    或使用make()函数来创建切片:
    var slice1 []type = make([]type, len)
    也可以简写为:slice1 := make([]type, len)
    
    也可以指定容量,其中capacity为可选参数。
    make([]T, length, capacity)
    len为数组大小,也是切片的初始化长度。
    
    len() 和 cap() 函数
    切片是可索引的,并且可以由 len() 方法获取长度。
    切片提供了计算容量的方法 cap() 可以测量切片最长可以达到多少。
    例如:
    func main() {
       var numbers = make([]int,3,5)
       printSlice(numbers)
    }
    
    func printSlice(x []int){
       fmt.Printf("len=%d cap=%d slice=%v
    ",len(x),cap(x),x)
    }
    输出结果为:len=3 cap=5 slice=[0 0 0]
    
    切片截取:通过设置下限及上限来设置截取切片 [lower-bound:upper-bound]。
    
    append() 和 copy() 函数
    
    append()函数用于追加切片元素,实现动态添加。
    copy()函数用于实现复制切片,
    var numbers []int
       /* 允许追加空切片 */
       numbers = append(numbers, 0)
       /* 向切片添加一个元素 */
       numbers = append(numbers, 1)
       /* 同时添加多个元素 */
       numbers = append(numbers, 2,3,4)
    
       /* 创建切片 numbers1 是之前切片的两倍容量*/
       numbers1 := make([]int, len(numbers), (cap(numbers))*2)
       /* 拷贝 numbers 的内容到 numbers1 */
       copy(numbers1,numbers)
    
  6. go语言range范围

    Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对的 key 值。
    
    例如:
    nums:=[]int{2,3,5}
    for i, num := range nums {
            if num == 3 {
                fmt.Println("index:", i)
            }
        }
    i表示索引,num表示返回的值。
    
    
  7. go语言Map集合

定义Map集合:
/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type

/* 使用 make 函数 */
map_variable := make(map[key_data_type]value_data_type)
注意:如果不初始化 map,那么就会创建一个 nil map。nil map 不能用来存放键值对

 var countryCapitalMap map[string]string /*创建集合 */

    /* map插入key - value对,各个国家对应的首都 */
    countryCapitalMap [ "France" ] = "巴黎"

    /*使用键输出地图值 */ 
    for country := range countryCapitalMap {
        fmt.Println(country, "首都是", countryCapitalMap [country])
    }

    /*查看元素在集合中是否存在 */
    capital, ok := countryCapitalMap [ "American" ] /*如果确定是真实的,则存在,否则不存在 */
    if (ok) {
        fmt.Println("American 的首都是", capital)
    } else {
        fmt.Println("American 的首都不存在")
    }

delete() 函数
delete() 函数用于删除集合的元素, 参数为 map 和其对应的 key。
例如:delete(countryCapitalMap, "France")
  1. go语言递归函数

    例如:使用递归求斐波那契数列
    func fibonacci(n int) int {
      if n < 2 {
       return n
      }
      return fibonacci(n-2) + fibonacci(n-1)
    }
    
    func main() {
        var i int
        for i = 0; i < 10; i++ {
           fmt.Printf("%d	", fibonacci(i))
        }
    }
    
  2. go 类型转换

    type_name(expression)
    type_name 为类型名称,expression为表达式。
    例如:
    var sum int = 17
       var count int = 5
       var mean float32
       
       mean = float32(sum)/float32(count)
    //将count和sum转换为浮点数
    
  3. go语言接口

    Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。
    /* 定义接口 */
    type interface_name interface {
       method_name1 [return_type]
       method_name2 [return_type]
       method_name3 [return_type]
       ...
       method_namen [return_type]
    }
    
    /* 定义结构体 */
    type struct_name struct {
       /* variables */
    }
    
    /* 实现接口方法 */
    func (struct_name_variable struct_name) method_name1() [return_type] {
       /* 方法实现 */
    }
    
    例如:
    type Phone interface {
        call()
    }
    
    type NokiaPhone struct {
    }
    
    func (nokiaPhone NokiaPhone) call() {
        fmt.Println("I am Nokia, I can call you!")
    }
    
    type IPhone struct {
    }
    
    func (iPhone IPhone) call() {
        fmt.Println("I am iPhone, I can call you!")
    }
    
    func main() {
        var phone Phone
    
        phone = new(NokiaPhone)
        phone.call()
    
        phone = new(IPhone)
        phone.call()
    }
    结果输出为:I am Nokia, I can call you!
    		  I am iPhone, I can call you!
    go接口类似于java接口,里面只是定义了方法没有具体的实现,实现交由实现类完成,这里交给其他类型,只要是实现了接口中的方法就行。
    
原文地址:https://www.cnblogs.com/jasonboren/p/11394897.html