zoukankan      html  css  js  c++  java
  • Go语言基础介绍

     Go是一个开源的编程语言。Go语言被设计成一门应用于搭载Web服务器,存储集群或类似用途的巨型中央服务器的系统编程语言。目前,Go最新发布版本为1.10.

            Go语言可以运行在Linux、FreeBSD、Mac OS X和Windows系统上。

            1. 结构:Go语言的基础组成有以下几个部分:包声明、引入包、函数、变量、语句&表达式、注释。

            (1)、必须在源文件中非注释的第一行指明这个文件属于哪个包,如:package main

            (2)、注释与C++相同,有单行注释即”//”和多行注释即”/* … */”两种。

            (3)、当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出;标识符如果以小写字母开头,则对包外是不可见的,但是它们在整个包的内部是可见并且可用的。

            2.  基础语法:

            (1)、Go标记:Go程序可以由多个标记组成,可以是关键字、标识符、常量、字符串、字符。

            (2)、行分隔符:在Go程序中,一行代表一个语句结束。每个语句不需要像C++语言一样以分号”;”结尾,因为这些工作都将由Go编译器自动完成。如果你打算将多个语句写在同一行,它们必须使用”;”为区分,但在实际开发中我们并不鼓励这种做法。

            (3)、注释:注释不会被编译,每一个包应该有相关注释。单行注释以”//”开头,多行注释以”/*”开头,以”*/”结尾,与C++相同。

            (4)、标识符:用来命名变量、类型等程序实体。一个标识符实际上就是一个或是多个字母(A~Z和a~z)、数字(0~9)、下划线”_”组成的序列,但是第一个字符必须是字母或下划线而不能是数字。标识符不能是Go语言的关键字。

            (5)、关键字: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。36个预定义标识符:append、bool、type、cap、close、complex、complex64、complex128、uint16、copy、false、float32、float64、image、int、int8、int16、uint32、int32、int64、iota、len、make、new、nil、panic、unit64、print、println、real、recover、string、true、uint、uint8、uintptr。

            程序一般由关键字、常量、变量、运算符、类型和函数组成。程序中可能会使用到这些分隔符:()、[]、{}。程序中可能会使用到这些标点符号:.、,、;、:和…。

            3. 数据类型:在Go编程语言中,数据类型用于声明函数和变量:布尔型(true、false);数字类型(整型、浮点型、复数);字符串类型(一串固定长度的字符连接起来的字符序列);派生类型(指针类型、数组类型、结构化类型、Channel类型、函数类型、切片类型、接口类型、Map类型)。

            4. 变量:声明变量的一般形式是使用var关键字。也可多变量声明。

            变量声明方式:(1)、指定变量类型,声明后若不赋值,使用默认值;(2)、根据值自行判定变量类型;(3)、省略var,注意:=左侧的变量不应该是已经声明过的,否则会导致编译错误。

            值类型和引用类型:所有像int、float、bool和string这些基本类型都属于值类型,使用这些类型的变量直接指向存在内存中的值。你可以通过&i来获取变量i的内存地址。值类型的变量的值存储在栈中。内存地址会根据机器的不同而有所不同,甚至相同的程序在不同的机器上执行后也会有不同的内存地址。因为每台机器可能有不同的存储器布局,并且位置分配也可能不同。更复杂的数据通常会需要使用多个字,这些数据一般使用引用类型保存。一个引用类型的变量r1存储的是r1的值所在的内存地址(数字),或内存地址中第一个字所在的位置。这个内存地址称之为指针,这个指针实际上也被存在另外的某一个字中。同一个引用类型的指针指向的多个字可以是连续的内存地址中(内存布局是连续的),也可以将这些字分散存放在内存中,每个字都指示了下一个字所在的内存地址。

            简短形式,使用:=赋值操作符:我们知道可以在变量的初始化时省略变量的类型而由系统自动推断,声明语句写上var关键字其实是显得多余了,因此我们可以将它们简写为:a:= 5 或b := false,a和b的类型(int和bool)将由编译器自动推断。这是使用变量的首选形式,但是它只能被用在函数体内,而不可以用于全局变量的声明与赋值。

            注意事项:(1)、如果在相同的代码块中,我们不可以再次对于相同名称的变量使用初始化声明。(2)、如果你声明了一个局部变量却没有在相同的代码块中使用它,同样会得到编译错误。但是全局变量是允许声明但不使用。同一类型的多个变量可以声明在同一行。

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

            多个变量可以声明在同一行,多个变量也可以在同一行进行赋值,这被称为并行或同时赋值。并行赋值也被用于当一个函数返回多个返回值时。

            5. 常量:是一个简单值的标识符,在程序运行时,不会被修改的量。常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。

            你可以省略类型说明符,因为编译器可以根据变量的值来推断其类型。也可以在同一行声明多个常量和赋值。常量还可以用作枚举。

            常量可以用len()、cap()、unsafe.Sizeof()函数计算表达式的值。常量表达式中,函数必须是内置函数。

            iota:特殊常量,可以认为是一个可以被编译器修改的常量。在每一个const关键字出现时,被重置为0,然后再下一个const出现之前,每出现一次iota,其所代表的数字会自动增加1。iota可以被用作枚举值。

            6. 运算符:用于在程序运行时执行数学或逻辑运算。

            Go语言内置的运算符有:算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符、其它运算符。

            算术运算符:+、-、*、/、%、++、--

            关系运算符:==、!=、>、<、>=、<=

            逻辑运算符:&&、||、!

            位运算符:&、|、^、<<、>>,对整数在内存中的二进制位进行操作。

            赋值运算符:=、+=、-=、*=、/=、%=、<<=、>>=、&=、^=、|=

            其它运算符:&(获取变量存储地址)、*(指针变量)

            运算符优先级:二元运算符的运算方向均是从左至右。可以使用括号来临时提升某个表达式的整体运算优先级。

            7. 条件语句:需要开发者通过指定一个或多个条件,并通过测试条件是否为true来决定是否执行指定语句,并在条件为false的情况下执行另外的语句。

            if语句:由布尔表达式后紧跟一个或多个语句组成。if语句后可以使用可选的else语句。你也可以在if或else if语句中嵌入一个或多个if或else if语句。

            switch语句:用于基于不同条件执行不同动作,每一个case分支都是唯一的,从上到下逐一检查,直到匹配为止。匹配项后面也不需要再加break。case类型不被局限于常量或整数,但必须是相同的类型。switch语句还可以被用于type--switch来判断某个interface变量中实际存储的变量类型。

            select语句:select是Go中的一个控制结构,类似于用于通信的switch语句。每个case必须是一个通信操作,要么是发送要么是接收。select随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。一个默认的子句应该总是可运行的。select语句的语法:(1)、每个case都必须是一个通信;(2)、所有channel表达式都会被求值;(3)、所有被发送的表达式都会被求值;(4)、如果任意某个通信可以进行,它就执行,其它被忽略;(5)、如果有多个case都可以运行,select会随机公平地选出一个执行,其它不会执行。否则,如果有default子句,则执行该语句。如果没有default子句,select将阻塞,直到某个通信可以运行。Go不会重新对channel或值进行求值。

            8. 循环语句:for,可以嵌套一个或多个for。循环控制语句可以控制循环体内语句的执行过程,包括break、continue、goto。如果循环中条件语句永远不为false则会进行无限循环。有些类似于C语言中的for和while。

            break语句:(1)、用于循环语句中跳出循环,并开始执行循环之后的语句;(2)、在switch中在执行一条case后跳出语句的作用。

            continue语句:有点像break语句,但是continue不是跳出循环,而是跳过当前循环执行下一次循环语句。

            goto语句:可以无条件地转移到过程中指定的行。在结构化程序设计中一般不主张使用goto语句。

            9. 函数:是基本的代码块,用于执行一个任务。Go语言最少有个main()函数。函数声明告诉了编译器函数的名称、返回类型和参数。Go语言标准库提供了多种可动用的内置的函数。

            函数定义格式:func function_name([parameter list]) [return_types] {函数体}

            函数定义解析:(1)、func:函数由func开始声明。(2)、function_name:函数名称,函数名和参数列表一起构成了函数签名。(3)、parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,函数也可以不包含参数。(4)、return_types:返回类型,函数返回一列值。(5)、函数体:函数定义的代码集合。

            Go函数可以返回多个值。

            函数参数:函数如果使用参数,该变量可称为函数的形参。形参就像定义在函数体内的局部变量。调用函数,可以通过两种方式传递参数:值传递和引用传递。默认情况下,Go语言使用的是值传递,即在调用过程中不会影响到实际参数。

            值传递:是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

            引用传递:是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

            函数用法:(1)、函数作为值:函数定义后可作为值来使用。(2)、闭包:是匿名函数,可在动态编程中使用。匿名函数是一个”内联”语句或表达式。匿名函数的优越性在于可以直接使用函数内的变量,不必声明。(3)、方法:是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针。所有给定类型的方法属于该类型的方法集。

            10. 变量作用域:Go语言中变量可以在三个地方声明:局部变量、全局变量、形式参数。

            (1)、局部变量:在函数体内声明的变量称之为局部变量,它们的作用域只在函数体内,参数和返回值变量也是局部变量。

            (2)、全局变量:在函数体外声明的变量称之为全局变量,全局变量可以在整个包甚至外部包(被导出后)使用。全局变量可以在任何函数中使用。

            (3)、形式参数:函数定义中的变量称为形式参数。形式参数会作为函数的局部变量来使用。

            Go语言程序中全局变量与局部变量名称可以相同,但是函数内的局部变量会被优先考虑。

            11. 数组:是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型如整型、字符串或者自定义类型。数组元素可以通过索引(位置)来读取(或者修改),索引从0开始,第一个元素索引为0,第二个索引为1,以此类推。

            声明数组:Go语言数组声明需要指定元素类型及元素个数。数组长度必须是整数且大于0。

            初始化数组:初始化数组中{}中的元素个数不能大于[]中的数字。如果忽略[]中的数字不设置数字大小,Go语言会根据元素的个数来设置数组的大小。

            访问数组元素:数组元素可以通过索引(位置)来读取。格式为数组名后加中括号,中括号中为索引的值。

            多维数组:Go语言支持多维数组。

            向函数传递数组:如果你想向函数传递数组参数,你需要在函数定义时,声明形参为数组。

            12. 指针:变量是一种方便的占位符,用于引用计算机内存地址。Go语言的取地址符是&,放到一个变量前使用就会返回相应变量的内存地址。一个指针变量指向了一个值的内存地址。

            指针使用流程:定义指针变量;为指针变量赋值;访问指针变量中指向地址的值。在指针类型前面加上*号(前缀)来获取指针所指向的内容。

            空指针:当一个指针被定义后没有分配到任何变量时,它的值为nil。nil指针也为空指针。nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。

            指针数组:可以定义一个指针数组来存储地址。

            指向指针的指针:如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量。访问指向指针的指针变量值需要使用两个*号。

            向函数传递指针参数:只需要在函数定义的参数上设置为指针类型即可。通过引用或地址传参,在函数调用时可以改变其值。

            13. 结构体:Go语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型。结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。

            结构体定义需要使用type和struct语句。struct语句定义一个新的数据类型,结构体中有一个或多个成员。type语句设定了结构体的名称。一旦定义了结构体类型,它就能用于变量的声明。如果要访问结构体成员,需要使用点号(.)操作符。你可以像其它数据类型一样将结构体类型作为参数传递给函数。你可以定义指向结构体的指针类似于其它指针变量。

            14. 切片(slice):Go语言切片是对数组的抽象。Go数组的长度不可改变,Go中提供了一种灵活,功能强悍的内置类型切片(“动态数组”)。与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。有些类似于C++中的vector。

            你可以声明一个未指定大小的数组来定义切片,切片不需要说明长度,或使用make()函数来创建切片。

            切片是可索引的,并且可以用len()方法获取长度。切片提供了计算容量的方法cap()可以测量切片最长可以达到多少。一个空切片在未初始化之前默认为nil,长度为0.可以通过设置下限及上限来设置截取切片。

            如果想增加切片的容量,我们必须创建一个新的更大的切片并把原分片的内容都拷贝过来。可使用拷贝切片的copy方法,或向切片追加新元素的append方法。

            15. range关键字:Go语言中range关键字用于for循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引值,在集合中返回key-value对的key值。

            16. Map(集合):Map是一种无序的键值对的集合。Map最重要的一点是通过key来快速检索数据,key类似于索引,指向数据的值。Map是一种集合,所以我们可以像迭代数组和切片那样迭代它。Map是无序的,我们无法决定它的返回顺序,这是因为Map是使用hash表来实现的。

            可以使用内建函数make也可以使用map关键字来定义Map。如果不初始化map,那么就会创建一个nil map。nil map不能用来存放键值对。delete()函数用来删除集合的元素。

            17. 递归函数:递归,就是在运行的过程中调用自己。在使用递归时,需要设置退出条件,否则递归将陷入无限循环中。

            18. 类型转换:用于将一种数据类型的变量转换为另外一种类型的变量,形式为:type_name(expression)

            19. 接口:把所有的具有共性的方法定义在一起,任何其它类型只要实现了这些方法就是实现了这个接口。

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

            以下是测试代码:

    [plain] view plain copy
     
    1. // 变量相关测试代码  
    2. package main  
    3.   
    4. import "fmt"  
    5.   
    6. // 全局变量声明  
    7. var c float32  
    8. var x = 11  
    9.   
    10. func main() {  
    11.     // 局部变量声明  
    12.     // 指定变量类型,声明后若不赋值,使用默认值  
    13.     var available bool  
    14.     available = true  
    15.     fmt.Println(available)  
    16.   
    17.     // 根据值自动判定变量类型  
    18.     var a = 1  
    19.     var b = 2.5  
    20.     fmt.Println(a, b)  
    21.   
    22.     c = float32(a) + float32(b)  
    23.     fmt.Printf("c = %f ", c)  
    24.   
    25.     // 省略var, 注意 :=左侧的变量不应该是已经声明过的,否则会导致编译错误,这种形式只能被用在函数体中  
    26.     valid := false  
    27.     _, d := 5, 6 // 空白标识符  
    28.     fmt.Println(valid, d)  
    29.   
    30.     // 多变量声明  
    31.     var enabled, disabled = true, "111"  
    32.     fmt.Println(enabled, disabled)  
    33.   
    34.     // 获取变量a的内存地址  
    35.     fmt.Println(&a)  
    36.   
    37.     // Go语言程序中全局变量与局部变量名称可以相同,但是函数内的局部变量会被优先考虑  
    38.     var x = -11  
    39.     fmt.Printf("x = %d ", x)  
    40. }  
    [plain] view plain copy
     
    1. // 常量相关测试代码  
    2. package main  
    3.   
    4. import "fmt"  
    5. import "unsafe"  
    6.   
    7. // 常量还可以用作枚举  
    8. const (  
    9.     o = "abc"  
    10.     p = len(o)  
    11.     q = unsafe.Sizeof(o)  
    12. )  
    13.   
    14. // itoa: iota可以被用作枚举值,第一个iota等于0,每当iota在新的一行被使用时,它的值都会自动加1  
    15. const (  
    16.     d = iota  
    17.     e  
    18.     f  
    19. )  
    20.   
    21. func main() {  
    22.     const a string = "abc" // 显示类型定义  
    23.     const b = "def"        // 隐式类型定义  
    24.     fmt.Println(a, b)  
    25.   
    26.     const x, y, z = 1, 0.2, "blog"  
    27.     fmt.Println(x, y, z)  
    28.   
    29.     fmt.Println(o, p, q)  
    30.   
    31.     fmt.Println(d, e, f)  
    32. }  
    [plain] view plain copy
     
    1. // 运算符相关测试代码  
    2. package main  
    3.   
    4. import "fmt"  
    5.   
    6. func main() {  
    7.     // 算术运算符  
    8.     var a, b, c = 1, 2, 3  
    9.     fmt.Printf("a + b = %d ", a+b)  
    10.     fmt.Printf("a - c = %d ", a-c)  
    11.     fmt.Printf("a * b = %d ", a*b)  
    12.     c++ // 注:++和--好像仅有前缀运算符  
    13.     fmt.Printf("c++ = %d ", c)  
    14.     b--  
    15.     fmt.Printf("--b = %d ", b)  
    16.   
    17.     // 关系运算符  
    18.     if a > b { // 注:visual studio code会默认把if (a > b)调整为if a > b  
    19.         fmt.Printf("a > b ")  
    20.     } else {  
    21.         fmt.Printf("a <= b ")  
    22.     }  
    23.   
    24.     // 逻辑运算符  
    25.     x, y := true, false  
    26.     if x && y {  
    27.         fmt.Printf("true ")  
    28.     } else {  
    29.         fmt.Printf("false ")  
    30.     }  
    31.   
    32.     // 位运算符: 好像仅支持整数  
    33.     a, b = 1, 3  
    34.     c = a & b  
    35.     fmt.Printf("c = %d ", c)  
    36.     fmt.Printf("b << 2: %d ", b<<2)  
    37.   
    38.     // 赋值运算符  
    39.     b <<= 2  
    40.     fmt.Printf("b = %d ", b)  
    41.   
    42.     // 其它运算符:&、*  
    43.     fmt.Printf("b's address: %0x ", &b)  
    44.     var ptr *int  
    45.     ptr = &a  
    46.     fmt.Printf("pointer: %0x ", ptr)  
    47. }  
    [plain] view plain copy
     
    1. // 条件语句相关测试代码  
    2. package main  
    3.   
    4. import "fmt"  
    5.   
    6. func main() {  
    7.     // if  
    8.     a := 1.2  
    9.     if a > 0 {  
    10.         fmt.Printf("a > 0, a = %f ", a)  
    11.     }  
    12.   
    13.     // if else  
    14.     b := 2.5  
    15.     if b > 10 {  
    16.         fmt.Printf("b > 10 ")  
    17.     } else {  
    18.         fmt.Printf("b <= 10 ")  
    19.     }  
    20.     fmt.Printf("b = %f ", b)  
    21.   
    22.     // if 嵌套  
    23.     if a > 0 {  
    24.         if b > 0 {  
    25.             fmt.Printf("a > 0, b > 0 ")  
    26.         }  
    27.     }  
    28.   
    29.     // switch  
    30.     grade := "B"  
    31.     marks := 90  
    32.     switch marks {  
    33.     case 90:  
    34.         grade = "A"  
    35.     case 80:  
    36.         grade = "B"  
    37.     case 50, 60:  
    38.         grade = "C"  
    39.     default:  
    40.         grade = "D"  
    41.     }  
    42.     fmt.Printf("grade = %s ", grade)  
    43.   
    44.     // type switch  
    45.     var x interface{}  
    46.   
    47.     switch i := x.(type) {  
    48.     case nil:  
    49.         fmt.Printf(" x 的类型: %T ", i)  
    50.     case int:  
    51.         fmt.Printf("x 是 int 型 ")  
    52.     case float64:  
    53.         fmt.Printf("x 是 float64 型 ")  
    54.     case func(int) float64:  
    55.         fmt.Printf("x 是 func(int) 型 ")  
    56.     case bool, string:  
    57.         fmt.Printf("x 是 bool 或 string 型 ")  
    58.     default:  
    59.         fmt.Printf("未知型 ")  
    60.     }  
    61.   
    62.     // select  
    63.     var c1, c2, c3 chan int  
    64.     var i1, i2 int  
    65.     select {  
    66.     case i1 = <-c1:  
    67.         fmt.Printf("received ", i1, " from c1 ")  
    68.     case c2 <- i2:  
    69.         fmt.Printf("sent ", i2, " to c2 ")  
    70.     case i3, ok := (<-c3): // same as: i3, ok := <-c3  
    71.         if ok {  
    72.             fmt.Printf("received ", i3, " from c3 ")  
    73.         } else {  
    74.             fmt.Printf("c3 is closed ")  
    75.         }  
    76.     default:  
    77.         fmt.Printf("no communication ")  
    78.     }  
    79.   
    80. }  
    [plain] view plain copy
     
    1. // 循环语句相关测试代码  
    2. package main  
    3.   
    4. import "fmt"  
    5.   
    6. func main() {  
    7.     // for  
    8.     a, b := 0, 15  
    9.     fmt.Printf("a的值为: ")  
    10.     for a = 0; a < 10; a++ {  
    11.         fmt.Printf("  %d  ", a)  
    12.     }  
    13.     fmt.Printf(" ")  
    14.   
    15.     fmt.Printf("a的值为: ")  
    16.     for a < b {  
    17.         a++  
    18.         fmt.Printf("  %d  ", a)  
    19.     }  
    20.     fmt.Printf(" ")  
    21.   
    22.     // for嵌套、break  
    23.     var i, j int  
    24.     fmt.Printf("2到100之间的素数包括:")  
    25.     for i = 2; i < 100; i++ {  
    26.         for j = 2; j <= (i / j); j++ {  
    27.             if i%j == 0 {  
    28.                 break  
    29.             }  
    30.         }  
    31.         if j > (i / j) {  
    32.             fmt.Printf("  %d  ", i)  
    33.         }  
    34.     }  
    35.     fmt.Printf(" ")  
    36.   
    37.     // continue  
    38.     a = 0  
    39.     fmt.Printf("a的奇数:")  
    40.     for a < 20 {  
    41.         a++  
    42.         if a%2 == 0 {  
    43.             continue  
    44.         }  
    45.         fmt.Printf("  %d  ", a)  
    46.     }  
    47.     fmt.Printf(" ")  
    48.   
    49.     // goto  
    50.     a = 0  
    51.     fmt.Printf("打印a的值:")  
    52. Loop:  
    53.     for a < 10 {  
    54.         if a == 5 {  
    55.             a++  
    56.             goto Loop  
    57.         }  
    58.         fmt.Printf("  %d  ", a)  
    59.         a++  
    60.     }  
    61.     fmt.Printf(" ")  
    62. }  
    [plain] view plain copy
     
    1. // 函数相关测试代码  
    2. package main  
    3.   
    4. import (  
    5.     "fmt"  
    6.     "math"  
    7. )  
    8.   
    9. // 函数返回两个数的最大值,值传递  
    10. func max(num1, num2 int) int {  
    11.     var result int  
    12.   
    13.     if num1 > num2 {  
    14.         result = num1  
    15.     } else {  
    16.         result = num2  
    17.     }  
    18.     return result  
    19. }  
    20.   
    21. // 函数支持返回多个值,值传递  
    22. func swap(x, y string) (string, string) {  
    23.     return y, x  
    24. }  
    25.   
    26. // Go函数不支持C++中的函数重载,引用传递  
    27. func swap1(x *int, y *int) {  
    28.     var temp int  
    29.     temp = *x  
    30.     *x = *y  
    31.     *y = temp  
    32. }  
    33.   
    34. func getSequence() func() int {  
    35.     i := 0  
    36.     return func() int {  
    37.         i++  
    38.         return i  
    39.     }  
    40. }  
    41.   
    42. type Circle struct {  
    43.     radius float64  
    44. }  
    45.   
    46. func (c Circle) getArea() float64 {  
    47.     // c.radius 即为Circle类型对象中的属性  
    48.     return 3.14 * c.radius * c.radius  
    49. }  
    50.   
    51. func main() {  
    52.     a, b := 100, 200  
    53.     var ret = max(a, b)  
    54.     fmt.Printf("a,b最大值为: %d ", ret)  
    55.   
    56.     var x, y = "hello", "beijing"  
    57.     fmt.Printf("x: %s, y: %s ", x, y)  
    58.     m, n := swap(x, y)  
    59.     fmt.Printf("x: %s, y: %s ", x, y)  
    60.     fmt.Printf("m: %s, n: %s ", m, n)  
    61.   
    62.     p, q := -100, 500  
    63.     fmt.Printf("p: %d, q: %d ", p, q)  
    64.     swap1(&p, &q)  
    65.     fmt.Printf("p: %d, q: %d ", p, q)  
    66.   
    67.     // 函数用法:函数作为值  
    68.     getSquareRoot := func(x float64) float64 {  
    69.         return math.Sqrt(x)  
    70.     }  
    71.     fmt.Printf("square root: %f ", getSquareRoot(9))  
    72.   
    73.     // 函数用法:闭包  
    74.     nextNumber := getSequence()  
    75.     // 调用nextNumber函数,i 变量自增 1 并返回  
    76.     fmt.Println("i的值: %d", nextNumber())  
    77.     fmt.Println("i的值: %d", nextNumber())  
    78.     fmt.Println("i的值: %d", nextNumber())  
    79.   
    80.     // 创建新的函数nextNumber1,并查看结果  
    81.     nextNumber1 := getSequence()  
    82.     fmt.Println("i的值: %d", nextNumber1())  
    83.     fmt.Println("i的值: %d", nextNumber1())  
    84.   
    85.     // 函数用法:方法  
    86.     var c1 Circle  
    87.     c1.radius = 10.00  
    88.     fmt.Println("Area of Circle(c1) = ", c1.getArea())  
    89. }  
    [plain] view plain copy
     
    1. // 数组相关测试代码  
    2. package main  
    3.   
    4. import "fmt"  
    5.   
    6. func getAverage(arr []int, size int) float32 {  
    7.     var avg, sum float32  
    8.   
    9.     for i := 0; i < size; i++ {  
    10.         sum += float32(arr[i])  
    11.     }  
    12.     avg = sum / float32(size)  
    13.   
    14.     return avg  
    15. }  
    16.   
    17. func main() {  
    18.     // 一维数组  
    19.     const num = 10  
    20.     var n [num]int  
    21.   
    22.     for i := 0; i < num; i++ {  
    23.         n[i] = i + 100  
    24.     }  
    25.   
    26.     for j := 0; j < num; j++ {  
    27.         fmt.Printf("Element[%d] = %d ", j, n[j])  
    28.     }  
    29.   
    30.     // 初始化数组  
    31.     const num2 = 5  
    32.     var m = [num2]float32{0., 1., 2., 3., 4.}  
    33.     for i := 0; i < num2; i++ {  
    34.         fmt.Printf("Element[%d] = %f ", i, m[i])  
    35.     }  
    36.   
    37.     // 初始化二维数组并访问  
    38.     var a = [3][4]int{{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}}  
    39.     fmt.Printf("a[2][3]: %d ", a[2][3])  
    40.   
    41.     // 向函数传递数组  
    42.     var balance = []int{1000, 2, 3, 17, 50}  
    43.     avg := getAverage(balance, 5)  
    44.     fmt.Printf("平均值:%f ", avg)  
    45. }  
    [plain] view plain copy
     
    1. // 指针相关测试代码  
    2. package main  
    3.   
    4. import "fmt"  
    5.   
    6. const MAX int = 3  
    7.   
    8. func swap(x *int, y *int) {  
    9.     var temp int  
    10.     temp = *x  
    11.     *x = *y  
    12.     *y = temp  
    13. }  
    14.   
    15. func main() {  
    16.     // 指针常规操作  
    17.     var a = 20  
    18.     var ip *int  
    19.   
    20.     ip = &a  
    21.   
    22.     fmt.Printf("a 变量的地址是: %x ", &a)  
    23.     fmt.Printf("ip 变量储存的指针地址: %x ", ip)  
    24.     fmt.Printf("*ip 变量的值: %d ", *ip)  
    25.   
    26.     var ptr *int  
    27.     fmt.Printf("ptr 的值为 : %x ", ptr)  
    28.     if ptr == nil {  
    29.         fmt.Printf("ptr为空指针 ")  
    30.     }  
    31.   
    32.     // 指针数组  
    33.     b := []int{10, 100, 200}  
    34.     var ptr2 [MAX]*int  
    35.   
    36.     for i := 0; i < MAX; i++ {  
    37.         ptr2[i] = &b[i]  
    38.     }  
    39.   
    40.     for i := 0; i < MAX; i++ {  
    41.         fmt.Printf("b[%d] = %d ", i, *ptr2[i])  
    42.     }  
    43.   
    44.     // 指向指针的指针  
    45.     var pptr **int  
    46.     pptr = &ip  
    47.     fmt.Printf("指向指针的指针变量 **pptr = %d ", **pptr)  
    48.   
    49.     // 向函数传递指针参数  
    50.     x, y := -11, 22  
    51.     fmt.Printf("x = %d, y = %d ", x, y)  
    52.     swap(&x, &y)  
    53.     fmt.Printf("x = %d, y = %d ", x, y)  
    54. }  
    [plain] view plain copy
     
    1. // 结构体相关测试代码  
    2. package main  
    3.   
    4. import "fmt"  
    5.   
    6. type Books struct {  
    7.     title   string  
    8.     author  string  
    9.     subject string  
    10.     book_id int  
    11. }  
    12.   
    13. func main() {  
    14.     // 访问结构体成员  
    15.     var Book1, Book2 Books  
    16.   
    17.     Book1 = Books{"Go语言", "www.runoob.com", "Go语言教程", 649507}  
    18.   
    19.     Book2.title = "Python 教程"  
    20.     Book2.author = "www.runoob.com"  
    21.     Book2.subject = "Python 语言教程"  
    22.     Book2.book_id = 6495700  
    23.   
    24.     fmt.Printf("Book 1 title: %s, autor: %s, subject: %s, book_id: %d ",  
    25.         Book1.title, Book1.author, Book1.subject, Book1.book_id)  
    26.   
    27.     fmt.Printf("Book 2 title: %s, autor: %s, subject: %s, book_id: %d ",  
    28.         Book2.title, Book2.author, Book2.subject, Book2.book_id)  
    29.   
    30.     // 结构体作为函数参数  
    31.     printBook(Book1)  
    32.     printBook(Book2)  
    33.   
    34.     // 结构体指针  
    35.     printBook2(&Book1)  
    36.     printBook2(&Book2)  
    37. }  
    38.   
    39. func printBook(book Books) {  
    40.     fmt.Printf("Book 1 title: %s, autor: %s, subject: %s, book_id: %d ",  
    41.         book.title, book.author, book.subject, book.book_id)  
    42. }  
    43.   
    44. func printBook2(book *Books) {  
    45.     fmt.Printf("Book 1 title: %s, autor: %s, subject: %s, book_id: %d ",  
    46.         book.title, book.author, book.subject, book.book_id)  
    47. }  
    [plain] view plain copy
     
    1. // 切片(slice)相关测试代码  
    2. package main  
    3.   
    4. import "fmt"  
    5.   
    6. func main() {  
    7.     // 定义切片  
    8.     //var slice1 []int  
    9.     //slice2 := make([]int, 5)  
    10.     //slice3 := make([]int, 5, 10)  
    11.   
    12.     // 切片初始化  
    13.     //slice4 := []int{1, 2, 3}  
    14.     //var arr = [5]float32{0., 1., 2., 3., 4.}  
    15.     //slice5 := arr[:]  
    16.   
    17.     // len()和cap()函数  
    18.     var numbers = make([]int, 3, 5)  
    19.     printSlice(numbers)  
    20.   
    21.     // 空(nil)切片  
    22.     var number2 []int  
    23.     printSlice(number2)  
    24.   
    25.     // 切片截取  
    26.     numbers3 := []int{0, 1, 2, 3, 4, 5, 6, 7, 8}  
    27.     printSlice(numbers3)  
    28.   
    29.     fmt.Println("numbers3 ==", numbers3)  
    30.   
    31.     // 打印子切片从索引1(包含) 到索引4(不包含)  
    32.     fmt.Println("numbers3[1:4] ==", numbers3[1:4])  
    33.     // 默认下限为  
    34.     fmt.Println("numbers3[:3] ==", numbers3[:3])  
    35.     // 默认上限为 len(s)  
    36.     fmt.Println("numbers3[4:] ==", numbers3[4:])  
    37.   
    38.     // 增加切片的容量  
    39.     var numbers4 []int  
    40.     printSlice(numbers4)  
    41.   
    42.     // 允许追加空切片  
    43.     numbers4 = append(numbers4, 0)  
    44.     printSlice(numbers4)  
    45.   
    46.     // 向切片添加一个元素  
    47.     numbers4 = append(numbers4, 1)  
    48.     printSlice(numbers4)  
    49.   
    50.     // 同时添加多个元素  
    51.     numbers4 = append(numbers4, 2, 3, 4)  
    52.     printSlice(numbers4)  
    53.   
    54.     // 创建切片 numbers5是之前切片的两倍容量  
    55.     numbers5 := make([]int, len(numbers4), (cap(numbers4))*2)  
    56.     printSlice(numbers5)  
    57.   
    58.     // 拷贝numbers4的内容到numbers5  
    59.     copy(numbers5, numbers4)  
    60.     printSlice(numbers5)  
    61. }  
    62.   
    63. func printSlice(x []int) {  
    64.     fmt.Printf("len=%d cap=%d slice=%v ", len(x), cap(x), x)  
    65. }  
    [plain] view plain copy
     
    1. // 范围(range)相关测试代码  
    2. package main  
    3.   
    4. import "fmt"  
    5.   
    6. func main() {  
    7.     // 使用range去求一个slice的和,使用数组跟这个很类似  
    8.     nums := []int{2, 3, 4}  
    9.     sum := 0  
    10.     for _, num := range nums {  
    11.         sum += num  
    12.     }  
    13.     fmt.Printf("sum: %d ", sum)  
    14.   
    15.     // 在数组上使用range将传入index和值两个变量,上面那个例子我们不需要使用该元素的序号,所以我们使用空白符"_"省略  
    16.     for i, num := range nums {  
    17.         if num == 3 {  
    18.             fmt.Printf("index: %d ", i)  
    19.         }  
    20.     }  
    21.   
    22.     // range也可以用在map的键值对上  
    23.     kvs := map[string]string{"a": "apple", "b": "banana"}  
    24.     for k, v := range kvs {  
    25.         fmt.Printf("%s -> %s ", k, v)  
    26.     }  
    27.   
    28.     // range也可以用来枚举Unicode字符串. 第一个参数是字符的索引,第二个是字符(Unicode的值)本身  
    29.     for i, c := range "go" {  
    30.         fmt.Println(i, c)  
    31.     }  
    32. }  
    [plain] view plain copy
     
    1. // Map(集合)相关测试代码  
    2. package main  
    3.   
    4. import "fmt"  
    5.   
    6. func main() {  
    7.     // 创建map  
    8.     var countryCapitalMap map[string]string  
    9.     countryCapitalMap = make(map[string]string)  
    10.   
    11.     // map插入key-value对,各个国家对应的首都  
    12.     countryCapitalMap["France"] = "Paris"  
    13.     countryCapitalMap["Italy"] = "Rome"  
    14.     countryCapitalMap["Japan"] = "Tokyo"  
    15.     countryCapitalMap["India"] = "New Delhi"  
    16.   
    17.     // 使用key输出map值  
    18.     for country := range countryCapitalMap {  
    19.         fmt.Printf("Capital of %s is %s ", country, countryCapitalMap[country])  
    20.     }  
    21.   
    22.     // 查看元素在集合中是否存在  
    23.     captial, ok := countryCapitalMap["United States"]  
    24.     // 如果ok是true,则存在,否则不存在  
    25.     if ok {  
    26.         fmt.Println("Capital of United States is", captial)  
    27.     } else {  
    28.         fmt.Println("Capital of United States is not present")  
    29.     }  
    30.   
    31.     // 创建map  
    32.     countryCapitalMap2 := map[string]string{"France": "Paris", "Italy": "Rome", "Japan": "Tokyo", "India": "New Delhi"}  
    33.     fmt.Println("原始 map:")  
    34.     for country := range countryCapitalMap2 {  
    35.         fmt.Println("Capital of", country, "is", countryCapitalMap2[country])  
    36.     }  
    37.   
    38.     // 删除元素  
    39.     delete(countryCapitalMap2, "France")  
    40.     fmt.Println("删除元素后 map:")  
    41.     for country := range countryCapitalMap2 {  
    42.         fmt.Println("Capital of", country, "is", countryCapitalMap2[country])  
    43.     }  
    44. }  
    [plain] view plain copy
     
    1. // 递归相关测试代码  
    2. package main  
    3.   
    4. import "fmt"  
    5.   
    6. func Factorial(n uint64) (result uint64) {  
    7.     if n > 0 {  
    8.         result = n * Factorial(n-1)  
    9.         return result  
    10.     }  
    11.     return 1  
    12. }  
    13.   
    14. func fibonacci(n int) int {  
    15.     if n < 2 {  
    16.         return n  
    17.     }  
    18.     return fibonacci(n-2) + fibonacci(n-1)  
    19. }  
    20.   
    21. func main() {  
    22.     // 阶乘  
    23.     var i = 15  
    24.     fmt.Printf("%d 的阶乘是 %d ", i, Factorial(uint64(i)))  
    25.   
    26.     // 斐波那契数列  
    27.     for i = 0; i < 10; i++ {  
    28.         fmt.Printf("%d ", fibonacci(i))  
    29.     }  
    30.     fmt.Println()  
    31. }  
    [plain] view plain copy
     
    1. // 接口相关测试代码  
    2. package main  
    3.   
    4. import "fmt"  
    5.   
    6. type Phone interface {  
    7.     call()  
    8. }  
    9.   
    10. type NokiaPhone struct {  
    11. }  
    12.   
    13. func (nokiaPhone NokiaPhone) call() {  
    14.     fmt.Println("I am Nokia, I can call you!")  
    15. }  
    16.   
    17. type IPhone struct {  
    18. }  
    19.   
    20. func (iPhone IPhone) call() {  
    21.     fmt.Println("I am iPhone, I can call you!")  
    22. }  
    23.   
    24. func main() {  
    25.     var phone Phone  
    26.   
    27.     phone = new(NokiaPhone)  
    28.     phone.call()  
    29.   
    30.     phone = new(IPhone)  
    31.     phone.call()  
    32. }  
    [plain] view plain copy
     
    1. // 错误处理相关测试代码  
    2. package main  
    3.   
    4. import "fmt"  
    5.   
    6. type DivideError struct {  
    7.     dividee int  
    8.     divider int  
    9. }  
    10.   
    11. // 实现'error'接口  
    12. func (de *DivideError) Error() string {  
    13.     strFormat := `  
    14.     Cannot proceed, the divider is zero.  
    15.     dividee: %d  
    16.     divider: 0  
    17.     `  
    18.     return fmt.Sprintf(strFormat, de.dividee)  
    19. }  
    20.   
    21. func Divide(varDividee int, varDivider int) (result int, errorMsg string) {  
    22.     if varDivider == 0 {  
    23.         dData := DivideError{varDividee, varDivider}  
    24.         errorMsg = dData.Error()  
    25.         return  
    26.     } else {  
    27.         return varDividee / varDivider, ""  
    28.     }  
    29. }  
    30.   
    31. func main() {  
    32.     // 正常情况  
    33.     if result, errorMsg := Divide(100, 10); errorMsg == "" {  
    34.         fmt.Println("100/10 = ", result)  
    35.     }  
    36.     // 当被除数为零的时候会返回错误信息  
    37.     if _, errorMsg := Divide(100, 0); errorMsg != "" {  
    38.         fmt.Println("errorMsg is: ", errorMsg)  
    39.     }  
    40. }  

            以上内容摘自:runoob.com
            GitHub: https://github.com/fengbingchun/Go_Test 

  • 相关阅读:
    【数据结构栈应用系列】括号匹配
    【二叉树系列】二叉树课程大作业
    Tomcat在Linux上的安装与配置
    索引介绍及创建与删除索引
    Java 内存溢出(java.lang.OutOfMemoryError)的常见情况和处理方式总结
    Tomcat的配置文件server.xml叙述
    问题及解决方法
    Oracle DB 查看预警日志
    报表简介
    Nginx负载均衡与反向代理—《亿级流量网站架构核心技术》
  • 原文地址:https://www.cnblogs.com/weiguoaa/p/9110308.html
Copyright © 2011-2022 走看看