博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
go语言学习
阅读量:6812 次
发布时间:2019-06-26

本文共 11690 字,大约阅读时间需要 38 分钟。

hot3.png

go语言菜鸟教程:

实效go编程:

在线go运行环境:

go的安装:参照这里在Windows上安装非常easy:

go中文标准库(Ctrl+f):

go英文包索引与搜索引擎:

/**********************************************************************************************************************/

gofmt 程序将Go程序按照标准风格缩进、 对齐,保留注释并在需要时重新格式化。若你想知道如何处理一些新的代码布局,请尝试运行 gofmt

分号并不在源码中出现。词法分析器会自动插入分号。可以概括为: “如果新行前的标记为语句的末尾,则插入分号”。左大括号不能放在下一行,如果这样做,就会在大括号前面插入一个分号,这可能引起不需要的效果。 

Go不再使用 do 或 while 循环,只有一个更通用的 forswitch 要更灵活一点;if 和 switch 像 for一样可接受可选的初始化语句; 此外,还有一个包含类型选择和多路通信复用器的新控制结构:select。 其语法也有些许不同:没有圆括号,而其主体必须始终使用大括号括住。

在变量与运算符间加入空格,程序看起来更加美观。

Go 语言数据类型

布尔型

布尔型的值只可以是常量 true 或者 false。一个简单的例子:var b bool = true。

数字类型

整型 int 和浮点型 float,Go 语言支持整型和浮点型数字,并且原生支持复数,其中位的运算采用补码。

Go 也有基于架构的类型,例如:int、uint 和 uintptr。uint8uint16uint32uint64int8int16int32int64

浮点型:float32、float64。complex64(32 位实数和虚数)complex128(64 位实数和虚数

字符串类型:

字符串就是一串固定长度的字符连接起来的字符序列。Go的字符串是由单个字节连接起来的。Go语言的字符串的字节使用UTF-8编码标识Unicode文本。

Go 语言变量

Go 语言变量名由字母、数字、下划线组成,其中首个字母不能为数字。

声明变量的一般形式是使用 var 关键字。

第一种,指定变量类型,声明后若不赋值,使用默认值,空指针为nil

var name typename = value

第二种,根据值自行判定变量类型

var name = valuevar e, f = 123, "hello"

第三种,省略var, 注意 :=左侧的变量不应该是已经声明过的,否则会导致编译错误。这种不带声明格式的只能在函数体中出现。由系统自动推断,初始化声明。

name := value//只能在函数体中出现// 例如var a int = 10var b = 10c : = 10

 第四种,多变量声明(重要)

//类型相同多个变量, 非全局变量var vname1, vname2, vname3 typevname1, vname2, vname3 = v1, v2, v3var vname1, vname2, vname3 = v1, v2, v3 //和python很像,不需要显示声明类型,自动推断vname1, vname2, vname3 := v1, v2, v3 //出现在:=左侧的变量不应该是已经被声明过的,否则会导致编译错误// 这种因式分解关键字的写法一般用于声明全局变量var (    vname1 v_type1    vname2 v_type2)

值类型和引用类型

所有像 int、float、bool 和 string 这些基本类型都属于值类型,使用这些类型的变量直接指向存在内存中的值。当使用等号 = 将一个变量的值赋值给另一个变量时,如:j = i,实际上是在内存中将 i 的值进行了拷贝。

如果你声明了一个局部变量却没有在相同的代码块中使用它,同样会得到编译错误(a declared and not used) 但是全局变量是允许声明但不使用。

多变量(已申明)可以在同一行进行赋值,如:

a, b, c = 5, 7, "abc"//未声明,用:=a, b, c := 5, 7, "abc"

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

Go 语言常量

const identifier [type] = value

常量还可以用作枚举:

const (    Unknown = 0    Female = 1    Male = 2)

神奇的iota

/*iota,特殊常量,可以认为是一个可以被编译器修改的常量。在每一个const关键字出现时,被重置为0,然后再下一个const出现之前,每出现一次iota,其所代表的数字会自动增加1。iota 可以被用作枚举值:*/const (    a = iota    b = iota    c = iota)//简写形式const (    a = iota    b    c)const (            a = iota   //0            b          //1            c          //2            d = "ha"   //独立值,iota += 1            e          //"ha"   iota += 1            f = 100    //iota +=1            g          //100  iota +=1            h = iota   //7,恢复计数            i          //8    )

一个更神奇的用法:

package mainimport "fmt"const (	i=1<

逻辑运算符&&  ||  !就是判断真假的

位运算符&, |, 和 ^

位运算符对整数在内存中的二进制位进行操作。对一个32位负数取非符号位的其他位a & 0x7fffffff

Go 语言 switch 语句

变量 var1 可以是任何类型,而 val1 和 val2 则可以是同类型的任意值。匹配项后面也不需要再加break,运行完后结束。

//Go 编程语言中 switch 语句的语法如下:switch var1 {    case val1:        ...    case val2:        ...    default:        ...}package mainimport "fmt"func main() {   /* 定义局部变量 */   var grade string = "B"   var marks int = 90   switch marks {      case 90: grade = "A"      case 80: grade = "B"      case 50,60,70 : grade = "C"      default: grade = "D"     }   switch {      case grade == "A" :         fmt.Printf("优秀!\n" )           case grade == "B", grade == "C" :         fmt.Printf("良好\n" )            case grade == "D" :         fmt.Printf("及格\n" )            case grade == "F":         fmt.Printf("不及格\n" )      default:         fmt.Printf("差\n" );   }   fmt.Printf("你的等级是 %s\n", grade );      }

Go 语言 select 语句

select是Go中的一个控制结构,类似于用于通信的switch语句。每个case必须是一个通信操作,要么是发送要么是接收。select随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。一个默认的子句应该总是可运行的。

以下描述了 select 语句的语法:

*每个case都必须是一个通信*所有channel表达式都会被求值*所有被发送的表达式都会被求值*如果任意某个通信可以进行,它就执行;其他被忽略。*如果有多个case都可以运行,Select会随机公平地选出一个执行。其他不会执行。 *否则:*如果有default子句,则执行该语句。*如果没有default字句,select将阻塞,直到某个通信可以运行;Go不会重新对channel或值进行求值。
package mainimport "fmt"func main() {   var c1, c2, c3 chan int   var i1, i2 int   select {      case i1 = <-c1:         fmt.Printf("received ", i1, " from c1\n")      case c2 <- i2:         fmt.Printf("sent ", i2, " to c2\n")      case i3, ok := (<-c3):  // same as: i3, ok := <-c3         if ok {            fmt.Printf("received ", i3, " from c3\n")         } else {            fmt.Printf("c3 is closed\n")         }      default:         fmt.Printf("no communication\n")   }    }

Go 语言 for 循环

搭配break,continue使用;Go语言的For循环有3中形式,只有其中的一种使用分号:

//和 C 语言的 for 一样:for init; condition; post { }//和 C 的 while 一样,取代while:for condition { }//和 C 的 for(;;) 一样:for { }

for 循环的 range 格式可以对 slice、map、数组、字符串等进行迭代循环。格式如下:

for key, value := range oldMap {    newMap[key] = value}

Go 语言函数

Go 语言函数定义格式如下:

func f(参数) (返回值) {   函数体}//返回多个值func swap(x, y string) (string, string) {   return y, x}/* 函数返回两个数的最大值 */func max(num1, num2 int) int {   var result int   if (num1 > num2) {      result = num1   } else {      result = num2   }   return result }

函数做为值使用:

package mainimport (   "fmt"   "math")func main(){   getSquareRoot := func(x float64) float64 {      return math.Sqrt(x)   }   fmt.Println(getSquareRoot(9))}

Go 语言匿名函数

func(参数列表) (返回值列表) {       函数体... }
//直接使用,无参数直接加括号    func() int {        var i int =5        fmt.Printf("func 1\n")        return i    }()   //直接使用,有参数,在括号里加参数    func(arge int)  {          fmt.Printf("func %d\n",arge)    }(2)  //也可以先赋给一个变量再调用   a := func() int {          fmt.Printf("func 3\n")          return 5     }   a()

Go 语言数组

  • 数组是值。将一个数组赋予另一个数组会复制其所有元素。
  • 切片保存了对底层数组的引用,若你将某个切片赋予另一个切片,它们会引用同一个数组。
  • 特别地,若将某个数组传入某个函数,它将接收到该数组的一份副本而非指针。
  • 数组的大小是其类型的一部分。类型 [10]int 和 [20]int 是不同的。

Go 语言数组声明需要指定元素类型及元素个数,语法格式如下:

var name [SIZE] type//var a [10] int//数组初始化:var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}//如果忽略[]中的数字不设置数组大小,Go 语言会根据元素的个数来设置数组的大小:var balance = []float32{1000.0, 2.0, 3.4, 7.0, 50.0}

Go 语言多维数组

var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type//var threedim [5][10][4]intvar a = [3][4]int{   {0, 1, 2, 3} ,   /*  第一行索引为 0 */ {4, 5, 6, 7} ,   /*  第二行索引为 1 */ {8, 9, 10, 11}   /*  第三行索引为 2 */}

Go 语言向函数传递数组

//指定大小void myFunction(param [10]int){...}//不指定大小void myFunction(param []int){...}//例子func getAverage(arr []int, size int) float32 {   var i,sum int   var avg float32     for i = 0; i < size;i++ {      sum += arr[i]   }   avg = float32(sum / size)   return avg;}

Go 语言指针

//指针声明格式如下:var name *type//打印指针地址%x:fmt.Printf("变量的地址: %x\n", &a )//Go 空指针,它的值为 nilif(ptr == nil)

Go 语言指针数组

声明整型指针数组(数组每个元素都是指针):var ptr [3]*int;

Go 语言指向指针的指针

var ptr **int;

Go 语言指针作为函数参数

func swap(x *int, y *int) {   var temp int   temp = *x    /* 保存 x 地址的值 */   *x = *y      /* 将 y 赋值给 x */   *y = temp    /* 将 temp 赋值给 y */

Go 语言结构体

定义结构体和声明变量

//结构体定义需要使用 type 和 struct 语句。//type 语句设定了结构体的名称。结构体的格式如下:type my_type struct {   name1 type1   name2 type2   ...}一旦定义了结构体类型,它就能用于变量的声明,语法格式如下:name := my_type {value1, value2...valuen}//例子:type Books struct {   title string   author string   subject string   book_id int}var Book1 BooksBook1.title = "Go 语言"Book1.author = "www.runoob.com"Book1.subject = "Go 语言教程"Book1.book_id = 6495407//结构体作为函数参数func printBook( book Books ) {}//结构体指针var ptr *Books

Go 语言切片(Slice)

Go 语言切片是对数组的抽象。Go 数组的长度不可改变。切片("动态数组"),长度是不固定的

切片保存了对底层数组的引用,若你将某个切片赋予另一个切片,它们会引用同一个数组。

声明一个未指定大小的数组来定义切片:var name []type或使用make()函数来创建切片:var slice1 []type = make([]type, len)或者make([]T, length, capacity)//capacity是可选参数也可以简写为:slice1 := make([]type, len)/************************************/s :=[] int {1,2,3 }            //直接初始化s := arr[:]                    //用数组初始化切片s := arr[startIndex:endIndex]  //新切片fmt.Printf("slice=%v\n",x)     //输出切片2种方法 结果:slice=[0 0 0]fmt.Println("slice=", x)func printSlice(x []int){      //这个函数用于输出切片信息   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)}if(numbers == nil){            //判断空切片      fmt.Printf("切片是空的")}

切片截取

package mainimport "fmt"func main() {   /* 创建切片 */   numbers := []int{0,1,2,3,4,5,6,7,8}      printSlice(numbers)   /* 打印原始切片 */   fmt.Println("numbers ==", numbers)   /* 打印子切片从索引1(包含) 到索引4(不包含)*/   fmt.Println("numbers[1:4] ==", numbers[1:4])   /* 默认下限为 0*/   fmt.Println("numbers[:3] ==", numbers[:3])   /* 默认上限为 len(s)*/   fmt.Println("numbers[4:] ==", numbers[4:])   numbers1 := make([]int,0,5)   printSlice(numbers1)   /* 打印子切片从索引  0(包含) 到索引 2(不包含) */   number2 := numbers[:2]   printSlice(number2)   /* 打印子切片从索引 2(包含) 到索引 5(不包含) */   number3 := numbers[2:5]   printSlice(number3)}func printSlice(x []int){   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)}

切片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)

Go 语言范围(Range)

//range一个切片,返回下标和对应项nums := []int{2, 3, 4}sum := 0for _, num := range nums {  sum += num}    //range也可以用在map的键值对上。    kvs := map[string]string{"a": "apple", "b": "banana"}    for k, v := range kvs {        fmt.Printf("%s -> %s\n", k, v)    }    //range也可以用来枚举Unicode字符串。    //第一个参数是字符的索引,第二个是字符(Unicode的值)本身。    for i, c := range "go" {        fmt.Println(i, c)    }    //结果:    0 103    1 111

Go 语言Map(集合)

Map 是一种无序的键值对的集合。Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。

/* 声明变量,默认 map 是 nil ,nil map 不能用来存放键值对*/var myname map[ktype]vtype/* 使用 make 函数,之后才能添加元素 */myname = make(map[ktype]vtype)
//例子   var countryCapitalMap map[string]string   /* 创建集合 */   countryCapitalMap = make(map[string]string)      /* map 插入 key-value 对,各个国家对应的首都 */   countryCapitalMap["France"] = "Paris"   countryCapitalMap["Italy"] = "Rome"   countryCapitalMap["Japan"] = "Tokyo"   countryCapitalMap["India"] = "New Delhi"      /* 使用 key 输出 map 值 */   for country := range countryCapitalMap {      fmt.Println("Capital of",country,"is",countryCapitalMap[country])   }      /* 查看元素在集合中是否存在 */   captial, ok := countryCapitalMap["United States"]   /* 如果 ok 是 true, 则存在,否则不存在 */   if(ok){      fmt.Println("Capital of United States is", captial)     }else {      fmt.Println("Capital of United States is not present")    }

map中删除元素

//delete(), 参数为 map 和其对应的 key/* 删除元素 */delete(countryCapitalMap,"France");

Go 语言类型转换

type(myname)   var a int = 17   var b int = 5   var c float32      c = float32(a)/float32(b)   fmt.Printf("c 的值为: %f\n",c)

Go 语言new

Go提供了两种分配原语,即内建函数 new 和 make

new不会初始化内存,只会将内存置零。 也就是说,new(T) 会为类型为 T 的新项分配已置零的内存空间, 并返回它的地址,也就是一个类型为 *T 的值。

Go 语言make

内建函数 make(T, args) 的目的不同于 new(T)

它只用于创建切片、映射和信道,并返回类型为 T(而非 *T)的一个已初始化 (而非置零)的值。 出现这种用差异的原因在于,这三种类型本质上为引用数据类型,它们在使用前必须初始化。

make 只适用于映射、切片和信道且不返回指针。若要获得明确的指针, 请使用 new 分配内存(如下)。

var p *[]int = new([]int)       // 分配切片结构;*p == nil;基本没用var v  []int = make([]int, 100) // 切片 v 现在引用了一个具有 100 个 int 元素的新数组// 没必要的复杂:var p *[]int = new([]int)*p = make([]int, 100, 100)// 习惯用法:v := make([]int, 100)

Go 错误处理

Go 语言通过内置的错误接口提供了非常简单的错误处理机制。

我们可以在编码中通过实现 error 接口类型来生成错误信息。

函数通常在最后的返回值中返回错误信息。

error类型是一个接口类型,这是它的定义:

type error interface {    Error() string}
package mainimport (	"fmt")// 定义一个 DivideError 结构type DivideError struct {	dividee int	divider int}// 实现`error`接口func (de *DivideError) Error() string {	strFormat := `	Cannot proceed, the divider is zero.	dividee: %d	divider: 0`	return fmt.Sprintf(strFormat, de.dividee)}// 定义 `int` 类型除法运算的函数func Divide(varDividee int, varDivider int) (result int, errorMsg string) {	if varDivider == 0 {		dData := DivideError{			dividee: varDividee,			divider: varDivider,		}		errorMsg = dData.Error()		return	} else {		return varDividee / varDivider, ""	}}func main() {	// 正常情况	if result, errorMsg := Divide(100, 10); errorMsg == "" {		fmt.Println("100/10 = ", result)	}	// 当被除数为零的时候会返回错误信息	if _, errorMsg := Divide(100, 0); errorMsg != "" {		fmt.Println("errorMsg is: ", errorMsg)	}}

 

转载于:https://my.oschina.net/zengjs275/blog/754547

你可能感兴趣的文章