Go语言程序基本结构以下:
A、包声明
B、引入包
C、函数
D、变量
E、语句 & 表达式
F、注释编程
package main //包声明 import "fmt" //引入包 func main(){ //main函数 //打印Hello World fmt.Print("Hello World!") }
Go语言程序由多个标记组成,能够是关键字、标识符、常量、字符串、符号。
fmt.Println("Hello, World!")语句由6个标记组成:数组
fmt . Println ( "Hello, World!" )
在Go语言程序中,一行表明一个语句结束。每一个语句不须要像C家族中的其它语言同样以分号;结尾。
若是打算将多个语句写在同一行,则必须使用;人为区分,但在实际开发中不推荐。闭包
fmt.Println("Hello, World!") fmt.Println("Hello, Go!")
注释不会被编译,每个包应该有相关注释。
单行注释是最多见的注释形式,能够在任何地方使用以 // 开头的单行注释。 多行注释也叫块注释,均已以 / 开头,并以 / 结尾。 app
//打印hello world /* It print to console a string */
标识符用来命名变量、类型等程序实体。标识符是由一个或是多个字母(A~Z和a~z)数字(0~9)、下划线_组成的序列,但第一个字符必须是字母或下划线而不能是数字。无效的标识符以下:
1ab(以数字开头)
case(Go语言的关键字)
a+b(运算符是不容许的)编程语言
Go语言有25个关键字或保留字:break,case,chan,const,continue,default,defer,else,fallthrough,for,func,go,goto,if,import,interface,map,package,range,return,select,struct,switch,type,var
Go语言有36个预约义标识符:append,bool,byte,cap,close,complex,complex64,complex128,copy,false,float32,float64,imag,int,int8,int16,int32,int64,iota,len,make,new,nil,panic,uint,uint8,uint16,uint32,uint64,uintptr,print,println,real,recover,string,true
程序通常由关键字、常量、变量、运算符、类型和函数组成。
程序中可能会使用到分隔符:括号 (),中括号 [] 和大括号 {}。
程序中可能会使用到标点符号:.、,、;、: 和 …。ide
Go语言中变量的声明必须使用空格隔开,如:var age int;
语句中适当使用空格能让程序看易阅读。
无空格:fruit=apples+oranges;
在变量与运算符间加入空格,程序看起来更加美观,如:fruit = apples + oranges;
函数
Go语言中,使用大小写来决定常量、变量、类型、接口、结构或函数是否能够被外部包所调用。
函数名首字母小写即为private : func getId() {}
函数名首字母大写即为public : func Printf() {}
布局
Go语言程序经过package来组织,只有package名称为main的包能够包含main函数。
一个可执行程序有且仅有一个main包。
经过import关键字来导入其余非main包。
能够经过import关键字单个导入: post
import "fmt" import "io"
也能够同时导入多个: 测试
import { "fmt", "io"}
或是:
import ( "fmt" )
使用<PackageName>.<FunctionName>
调用:
package别名:import fmt2 "fmt"
为fmt起别名为fmt2
省略调用:调用的时候只须要Println(),而不须要fmt.Println()import . "fmt"
前面加个点表示省略调用,那么调用该模块里面的函数,能够不用写模块名称:
import . "fmt" func main (){ Println("hello,world")}
在Go编程语言中,数据类型用于声明函数和变量。
数据类型是为了把数据分红所需内存大小不一样的数据,编程的时候须要用大数据的时候才须要申请大内存,就能够充分利用内存。
布尔型的值只能够是常量true或者false。var b bool = true
整型int和浮点型float32float64,Go语言支持整型和浮点型数字,而且原生支持复数,其中位的运算采用补码。
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:无符号整型,用于存放一个指针
字符串就是一串固定长度的字符链接起来的字符序列。Go语言的字符串是由单个字节链接起来的。Go语言的字符串的字节使用UTF-8编码标识Unicode文本。
派生类型包括:
A、指针类型(Pointer)
B、数组类型
C、结构化类型(struct)
D、Channel 类型
E、函数类型
F、切片类型
G、接口类型(interface)
H、Map 类型
变量是计算机语言中能储存计算结果或能表示值的抽象概念。变量能够经过变量名访问。
Go 语言变量名由字母、数字、下划线组成,其中首个字母不能为数字。
声明变量的通常形式使用var关键字:var identifier type
第一种,指定变量类型,声明后若不赋值,使用默认值。
var v_name v_type v_name = value
第二种,根据值自行断定变量类型。var v_name = value
第三种,省略var, 注意 :=左侧的变量不该该是已经声明过的,不然会致使编译错误。
v_name := value // 例如 var a int = 10 var b = 10 c := 10
//类型相同多个变量, 非全局变量 var vname1, vname2, vname3 type vname1, vname2, vname3 = v1, v2, v3 //不须要显示声明类型,自动推断 var vname1, vname2, vname3 = v1, v2, v3 //出如今:=左侧的变量不该该是已经被声明过的,不然会致使编译错误 vname1, vname2, vname3 := v1, v2, v3 //分解关键字的写法通常用于声明全局变量 var ( vname1 v_type1 vname2 v_type2 )
实例:
var x, y int var ( a int b bool ) var c, d int = 1, 2 var e, f = 123, "hello" //不带声明格式的只能在函数体中出现 //g, h := 123, "hello"
int、float、bool、string等基本类型都属于值类型,值类型的变量直接指向存在内存中的值。
当使用等号=将一个变量的值赋值给另外一个变量时,如:j = i,其实是在内存中将i的值进行拷贝。
能够经过&i来获取变量i的内存地址,例如0xf840000040(地址随机)。值类型的变量的值存储在栈中。
内存地址会根据机器的不一样而有所不一样,相同的程序在不一样的机器上执行后也会有不一样的内存地址。由于每台机器可能有不一样的存储器布局,而且位置分配也可能不一样。
更复杂的数据一般会须要使用多个字,通常使用引用类型保存。
一个引用类型的变量r1存储的是r1的值所在的内存地址(数字),或内存地址中第一个字所在的位置。
同一个引用类型的指针指向的多个字能够是在连续的内存地址中(内存布局是连续的),也能够将这些字分散存放在内存中,每一个字都指示了下一个字所在的内存地址。
当使用赋值语句r2 = r1时,只有引用(地址)被复制。
若是r1的值被改变,r1的全部引用都会指向被修改后的内容。
做用域为已声明标识符所表示的常量、类型、变量、函数或包在源代码中的做用范围。
Go语言中变量能够在三个地方声明:
A、函数内定义的变量称为局部变量
B、函数外定义的变量称为全局变量
C、函数定义中的变量称为形式参数
在函数体内声明的变量为局部变量,其做用域只在函数体内,参数和返回值变量也是局部变量。
package main import "fmt" func main() { /* 声明局部变量 */ var a, b, c int /* 初始化参数 */ a = 10 b = 20 c = a + b fmt.Printf ("结果: a = %d, b = %d and c = %d\n", a, b, c) }
在函数体外声明的变量为全局变量,全局变量能够在整个包甚至外部包(被导出后)使用。
package main import "fmt" /* 声明全局变量 */ var g int func main() { /* 声明局部变量 */ var a, b int /* 初始化参数 */ a = 10 b = 20 g = a + b fmt.Printf("结果: a = %d, b = %d and g = %d\n", a, b, g) }
Go语言程序中全局变量与局部变量名称能够相同,可是函数内的局部变量会被优先考虑。
package main import "fmt" /* 声明全局变量 */ var g int = 20 func main() { /* 声明局部变量 */ var g int = 10 fmt.Printf ("结果: g = %d\n", g) }
形式参数会做为函数的局部变量来使用。
package main import "fmt" /* 声明全局变量 */ var a int = 20; func main() { /* main 函数中声明局部变量 */ var a int = 10 var b int = 20 var c int = 0 fmt.Printf("main()函数中 a = %d\n", a); c = sum( a, b); fmt.Printf("main()函数中 c = %d\n", c); } /* 函数定义-两数相加 */ func sum(a, b int) int { fmt.Printf("sum() 函数中 a = %d\n", a); fmt.Printf("sum() 函数中 b = %d\n", b); return a + b; }
不一样类型的局部和全局变量默认值为:
int 0
float32 0
pointer nil
常量是一个简单值的标识符,在程序运行时,不会被修改的量。
常量中的数据类型只能够是布尔型、数字型(整数型、浮点型和复数)和字符串型。
常量的定义格式:const identifier [type] = value
能够省略类型说明符[type],由于编译器能够根据变量的值来推断其类型。
显式类型定义: const b string = "abc"
隐式类型定义: const b = "abc"
多个相同类型的声明能够简写为:const c_name1, c_name2 = value1, value2
常量使用实例:
package main import "fmt" func main() { const LENGTH int = 10 const WIDTH int = 5 var area int const a, b, c = 1, false, "str" //多重赋值 area = LENGTH * WIDTH fmt.Printf("面积为 : %d", area) println() println(a, b, c) }
常量能够用做枚举:
const ( Unknown = 0 Female = 1 Male = 2)
数字 0、1和2分别表明未知性别、女性和男性。
常量能够用len(), cap(), unsafe.Sizeof()函数计算表达式的值。常量表达式中,函数必须是内置函数。
package main import "unsafe" const ( a = "abc" b = len(a) c = unsafe.Sizeof(a) ) func main(){ println(a, b, c) }
Iota是一个特殊常量,是一个能够被编译器修改的常量。
在每个const关键字出现时,被重置为0,而后再下一个const出现以前,每出现一次iota,其所表明的数字会自动增长1。
iota能够被用做枚举值:
const ( a = iota b = iota c = iota )
第一个iota等于0,每当iota在新的一行被使用时,值都会自动加1,因此a=0, b=1, c=2能够简写为以下形式:
const ( a = iota b c )
使用实例:
package main import "fmt" func main() { 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 ) fmt.Println(a,b,c,d,e,f,g,h,i) }
存储数据的Byte、KB、MB、GB、TB、PB的计算:
const( b=1<<(10*iota) kb mb gb tb pb ) func dataByte() { fmt.Println("b=",b) fmt.Println("kb=",kb) fmt.Println("mb=",mb) fmt.Println("gb=",gb) fmt.Println("tb=",tb) fmt.Println("pb=",pb) }
运算符用于在程序运行时执行数学或逻辑运算。Go语言内置的运算符有:
A、算术运算符
B、关系运算符
C、逻辑运算符
D、位运算符
E、赋值运算符
F、其它运算符
+ 相加 A+B - 相减 A-B * 相乘 A*B / 相除 A/B % 求余 A%B ++ 自增 A++ -- 自减 A--
算术运算实例:
package main import "fmt" func main() { var a int = 21 var b int = 10 var c int c = a + b fmt.Printf("相加 - c 的值为 %d\n", c) c = a - b fmt.Printf("相减 - c 的值为 %d\n", c) c = a * b fmt.Printf("相乘 - c 的值为 %d\n", c) c = a / b fmt.Printf("相除 - c 的值为 %d\n", c) c = a % b fmt.Printf("求余 - c 的值为 %d\n", c) a++ fmt.Printf("自增 - a 的值为 %d\n", a) a-- fmt.Printf("自减 - a 的值为 %d\n", a) }
==:检查两个值是否相等,若是相等返回 True 不然返回 False。 !=:检查两个值是否不相等,若是不相等返回 True 不然返回 False。 >:检查左边值是否大于右边值,若是是返回 True 不然返回 False。 <:检查左边值是否小于右边值,若是是返回 True 不然返回 False。 >=:检查左边值是否大于等于右边值,若是是返回 True 不然返回 False。 <=:检查左边值是否小于等于右边值,若是是返回 True 不然返回 False。
&&:逻辑AND运算符。 若是两边的操做数都是True,则条件True,不然为False。 ||:逻辑OR运算符。 若是两边的操做数有一个True,则条件True,不然为False。 !:逻辑NOT运算符。 若是条件为True,则逻辑NOT条件False,不然为True。
&:按位与运算符"&"是双目运算符,功能是参与运算的两数各对应的二进位进行相与。 |:按位或运算符"|"是双目运算符,功能是参与运算的两数各对应的二进位进行相或。 ^:按位异或运算符"^"是双目运算符,功能是参与运算的两数各对应的二进位进行相异或,当两对应的二进位相异时,结果为1。 <<:左移运算符"<<"是双目运算符,左移n位就是乘以2的n次方,功能把"<<"左边的运算数的各二进位所有左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补0。 >>:右移运算符">>"是双目运算符,右移n位就是除以2的n次方,功能是把">>"左边的运算数的各二进位所有右移若干位,">>"右边的数指定移动的位数。
位运算实例:
package main import "fmt" func main() { var a uint = 60 /* 60 = 0011 1100 */ var b uint = 13 /* 13 = 0000 1101 */ var c uint = 0 c = a & b /* 12 = 0000 1100 */ fmt.Printf("& - c 的值为 %d\n", c ) c = a | b /* 61 = 0011 1101 */ fmt.Printf("| - c 的值为 %d\n", c ) c = a ^ b /* 49 = 0011 0001 */ fmt.Printf("^ - c 的值为 %d\n", c ) c = a << 2 /* 240 = 1111 0000 */ fmt.Printf("<< - c 的值为 %d\n", c ) c = a >> 2 /* 15 = 0000 1111 */ fmt.Printf(">> - c 的值为 %d\n", c ) }
=:简单的赋值运算符,将一个表达式的值赋给一个左值 +=:相加后再赋值 -=:相减后再赋值 *=:相乘后再赋值 /=:相除后再赋值 %=:求余后再赋值 <<=:左移后赋值 >>=:右移后赋值 &=:右移后赋值 ^=:按位异或后赋值 |=:按位或后赋值
赋值运算符实例:
package main import "fmt" func main() { var a int = 21 var c int c = a fmt.Printf("= 运算符实例,c 值为 = %d\n", c ) c += a fmt.Printf("+= 运算符实例,c 值为 = %d\n", c ) c -= a fmt.Printf("-= 运算符实例,c 值为 = %d\n", c ) c *= a fmt.Printf("*= 运算符实例,c 值为 = %d\n", c ) c /= a fmt.Printf("/= 运算符实例,c 值为 = %d\n", c ) c = 200; c <<= 2 fmt.Printf("<<= 运算符实例,c 值为 = %d\n", c ) c >>= 2 fmt.Printf(">>= 运算符实例,c 值为 = %d\n", c ) c &= 2 fmt.Printf("&= 运算符实例,c 值为 = %d\n", c ) c ^= 2 fmt.Printf("^= 运算符实例,c 值为 = %d\n", c ) c |= 2 fmt.Printf("|= 运算符实例,c 值为 = %d\n", c ) }
&:返回变量存储地址 *:指针变量
实例:
package main import "fmt" func main() { var a int = 4 var b int32 var c float32 var ptr *int /* 运算符实例 */ fmt.Printf("a 变量类型为 = %T\n", a ) fmt.Printf("b 变量类型为 = %T\n", b ) fmt.Printf("c 变量类型为 = %T\n", c ) fmt.Printf("ptr变量类型为 = %T\n", ptr) /* & 和 * 运算符实例 */ ptr = &a /* 'ptr' 包含了 'a' 变量的地址 */ fmt.Printf("a 的值为 %d\n", a); fmt.Printf("*ptr 为 %d\n", *ptr); }
有些运算符拥有较高的优先级,二元运算符的运算方向均是从左至右。
优先级 运算符
7 ^、! 6 * 、/、%、 <<、>>、&、^ 5 +、-、|、^ 4 ==、!=、<、<=、>=、> 3 <、- 2 && 1 ||
运算符优先级实例:
package main import "fmt" func main() { var a int = 20 var b int = 10 var c int = 15 var d int = 5 var e int e = (a + b) * c / d // ( 30 * 15 ) / 5 fmt.Printf("(a + b) * c / d 的值为 : %d\n", e) e = ((a + b) * c) / d // (30 * 15 ) / 5 fmt.Printf("((a + b) * c) / d 的值为 : %d\n", e) e = (a + b) * (c / d) // (30) * (15/5) fmt.Printf("(a + b) * (c / d) 的值为 : %d\n", e) e = a + (b*c)/d // 20 + (150/5) fmt.Printf("a + (b * c) / d 的值为 : %d\n", e) }
条件语句须要开发者经过指定一个或多个条件,并经过测试条件是否为 true来决定是否执行指定语句,并在条件为false的状况在执行另外的语句。
条件语句的结构以下:
if语句由一个布尔表达式后紧跟一个或多个语句组成。
Go编程语言中if语句的语法以下:
if 布尔表达式 { /* 在布尔表达式为 true 时执行 */}
If在布尔表达式为true时,其后紧跟的语句块执行,若是为false则不执行。
if语句后可使用可选的else语句, else语句中的表达式在布尔表达式为 false时执行。
Go编程语言中 if...else 语句的语法以下:
if 布尔表达式 { /* 在布尔表达式为 true 时执行 */} else { /* 在布尔表达式为 false 时执行 */}
If在布尔表达式为true时,其后紧跟的语句块执行,若是为false则执行 else语句块。
package main import "fmt" func main() { var a int = 100 var b int = 0 if a > b { println("a > b") } else { fmt.Println("a < b") } }
if或else if语句中嵌入一个或多个if或else if语句。
switch语句用于基于不一样条件执行不一样动做,每个case分支都是惟一的,从上直下逐一测试,直到匹配为止。
switch语句执行的过程从上至下,直到找到匹配项,匹配项后面也不须要再加break。
Go编程语言中switch语句的语法以下:
switch var1 { case val1: ... case val2: ... default: ...}
变量var1能够是任何类型,而val1和val2则能够是同类型的任意值。类型不被局限于常量或整数,但必须是相同的类型;或者最终结果为相同类型的表达式。能够同时测试多个可能符合条件的值,使用逗号分割它们,例如:case val1, val2, val3。
switch流程结构以下:
Switch实例以下:
package main import "fmt" func grade(score int)string{ var grade string; switch{ case score<0 && score > 100: fmt.Printf("score is error") grade = "Error" case score < 60: fmt.Printf("F") grade = "F" case score<80: fmt.Printf("C") grade = "C" case score<90: fmt.Printf("B") grade = "B" case score<=100: fmt.Printf("A") grade = "A" } return grade } func operator(a,b int, op string)int{ var result int switch op { case "+": result = a + b case "-": result = a -b case "*": result = a * b case "/": result = a / b default: panic("unsupported operator:" + op) } return result } func main() { grade(100) fmt.Println(operator(3,6,"+")) }
switch语句会自动break,不用每一个case分支都break,若是要取消break,可使用fallthrough。Switch后能够不带表达式。
switch语句还能够被用于type-switch来判断某个interface变量中实际存储的变量类型。
Type Switch语法格式以下:
switch x.(type){ case type: statement(s); case type: statement(s); /* 能够定义任意个数的case */ default: /* 可选 */ statement(s); }
实例:
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是Go中的一个控制结构,相似于用于通讯的switch语句。每一个case必须是一个通讯操做,要么是发送要么是接收。
select随机执行一个可运行的case。若是没有case可运行,它将阻塞,直到有case可运行。一个默认的子句应该老是可运行的。
Go编程语言中select语句的语法以下:
select { case communication clause: statement(s); case communication clause: statement(s); /* 能够定义任意数量的 case */ default: /* 可选 */ statement(s); }
select语句中:
A、每一个case都必须是一个通讯
B、全部channel表达式都会被求值,
C、全部被发送的表达式都会被求值,若是任意某个通讯能够进行,它就执行;其余被忽略。
D、若是有多个case均可以运行,Select会随机公平地选出一个执行。其余不会执行。
不然:
若是有default子句,则执行该语句。
若是没有default字句,select将阻塞,直到某个通讯能够运行;Go不会从新对channel或值进行求值。
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") } }
实际问题中有许多具备规律性的重复操做,所以在程序中就须要重复执行某些语句。
循环语句的结构以下:
for循环是一个循环控制结构,能够执行指定次数的循环。
G语言的for循环有3种形式,只有其中的一种使用分号。
for init; condition; post { } for condition { } for { }
init:通常为赋值表达式,给控制变量赋初值;
condition:关系表达式或逻辑表达式,循环控制条件;
post:通常为赋值表达式,给控制变量增量或减量。
for语句执行过程以下:
A、先对表达式init赋初值;
B、判别赋值表达式init是否知足给定条件,若其值为真,知足循环条件,则执行循环体内语句,而后执行post,进入第二次循环,再判别condition;不然判断condition的值为假,不知足条件,就终止for循环,执行循环体外语句。
for循环的range格式能够对 slice、map、数组、字符串等进行迭代循环。格式以下:
for key, value := range oldMap { newMap[key] = value}
for语句的流程结构以下:
实例以下:
package main import "fmt" func main() { var b int = 15 var a int numbers := [6]int{1, 2, 3, 5} /* for 循环 */ for a := 0; a < 10; a++ { fmt.Printf("a 的值为: %d\n", a) } for a < b { a++ fmt.Printf("a 的值为: %d\n", a) } for i,x:= range numbers { fmt.Printf("第 %d 位 x 的值 = %d\n", i,x) } }
Go语言容许用户在循环内使用循环。Go语言嵌套循环的格式:
for [condition | ( init; condition; increment ) | Range]{ for [condition | ( init; condition; increment ) | Range] { statement(s); } statement(s);}
循环嵌套实例:
package main import "fmt" func main() { /* 定义局部变量 */ var i, j int for i=2; i < 100; i++ { for j=2; j <= (i/j); j++ { if(i%j==0) { break; // 若是发现因子,则不是素数 } } if(j > (i/j)) { fmt.Printf("%d 是素数\n", i); } } }
循环控制语句能够控制循环体内语句的执行过程。GO语言支持如下三种循环控制语句:
A、break语句
常常用于中断当前for循环或跳出switch语句。
用于循环语句中跳出循环,并开始执行循环后的语句。
break在switch(开关语句)中在执行一条case后跳出语句的做用。
break 语法格式以下:break;
break语句流程结果以下:
/* 定义局部变量 */ var a int = 10 /* for 循环 */ for a < 20 { fmt.Printf("a 的值为 : %d\n", a); a++; if a > 15 { /* 使用 break 语句跳出循环 */ break; } }
B、continue语句
Go语言的continue语句用于跳过当前循环执行下一次循环语句。
for循环中,执行continue语句会触发for增量语句的执行。
continue语法格式以下:continue;
Continue语句流程结构以下:
/* 定义局部变量 */ var a int = 10 /* for 循环 */ for a < 20 { if a == 15 { /* 跳过这次循环 */ a = a + 1; continue; } fmt.Printf("a 的值为 : %d\n", a); a++; }
C、goto语句
Go语言的goto语句能够无条件地转移到过程当中指定的行。
goto语句一般与条件语句配合使用。可用来实现条件转移,构成循环,跳出循环体等功能。
在结构化程序设计中通常不主张使用goto语句,以避免形成程序流程的混乱,使理解和调试程序都产生困难。
goto语法格式以下:
goto label; ... label: statement;
goto语句流程结构以下:
/* 定义局部变量 */ var a int = 10 /* 循环 */ LOOP: for a < 20 { if a == 15 { /* 跳过迭代 */ a = a + 1 goto LOOP } fmt.Printf("a的值为 : %d\n", a) a++ }
若是循环中条件语句永远不为false,则会进行无限循环。能够经过for循环语句中只设置一个条件表达式来实现无限循环。
for true{ fmt.Printf("这是无限循环。\n"); }
函数是基本的代码块,用于执行一个任务。
Go语言最少有个main()函数。
能够经过函数来划分不一样功能,逻辑上每一个函数执行的是指定的任务。
函数声明告诉编译器函数的名称、返回类型和参数。
Go语言标准库提供了多种可用的内置的函数。例如,len()函数能够接受不一样类型参数并返回该类型的长度。若是传入的是字符串则返回字符串的长度,若是传入的是数组,则返回数组中包含的元素个数。
Go 语言函数定义格式以下:
func function_name( [parameter list] ) [return_types] { 函数体}
函数定义解析:
func:函数由func开始声明
function_name:函数名称,函数名和参数列表一块儿构成了函数签名。
parameter list:参数列表,参数就像一个占位符,当函数被调用时,能够将值传递给参数,传递的值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,函数能够不包含参数。
return_types:返回类型,函数返回一列值。return_types是返回值的数据类型。有些功能不须要返回值,return_types不是必须的。
函数体:函数定义的代码集合。
函数实例以下:
/* 函数返回两个数的最大值 */ func max(num1, num2 int) int { /* 声明局部变量 */ var result int if (num1 > num2) { result = num1 } else { result = num2 } return result }
当建立函数时,定义函数须要作什么,经过调用该函数来执行指定任务。
调用函数,向函数传递参数,并返回值,例如:
package main import "fmt" func main() { /* 定义局部变量 */ var a int = 100 var b int = 200 var ret int /* 调用函数并返回最大值 */ ret = max(a, b) fmt.Printf( "最大值是 : %d\n", ret ) } /* 函数返回两个数的最大值 */ func max(num1, num2 int) int { /* 定义局部变量 */ var result int if (num1 > num2) { result = num1 } else { result = num2 } return result }
Go语言函数能够返回多个值。
package main import "fmt" func swap(x, y string) (string, string) { return y, x } func main() { a, b := swap("Mahesh", "Kumar") fmt.Println(a, b) }
函数若是使用参数,参数变量称为函数的形参。
调用函数,能够经过两种方式来传递参数:
A、值传递
值传递是指在调用函数时将实际参数复制一份传递到函数中,在函数中若是对参数进行修改,将不会影响到实际参数。
B、引用传递
引用传递是指在调用函数时将实际参数的地址传递到函数中,在函数中对参数所进行的修改,将影响到实际参数。
默认状况下,Go 语言使用的是值传递,即在调用过程当中不会影响到实际参数。
A、函数做为值
Go语言能够很灵活的建立函数,并做为值使用。
package main import ( "fmt" "math" ) func main(){ /* 声明函数变量 */ getSquareRoot := func(x float64) float64 { return math.Sqrt(x) } /* 使用函数 */ fmt.Println(getSquareRoot(9)) }
B、闭包
Go语言支持匿名函数,可做为闭包。匿名函数是一个"内联"语句或表达式。匿名函数的优越性在于能够直接使用函数内的变量,没必要申明。
建立函数getSequence(),函数体内返回另一个函数。
func getSequence() func() int { i:=0 return func() int { i+=1 return i } }
C、方法
Go语言中同时有函数和方法。一个方法就是一个包含了接受者的函数,接受者能够是命名类型或者结构体类型的一个值或者是一个指针。全部给定类型的方法属于该类型的方法集。语法格式以下:
func (variable_name variable_data_type) function_name() [return_type]{ /* 函数体*/ }
方法实例以下:
/* 定义结构体 */ type Circle struct { radius float64 } //method 属于 Circle 类型对象中的方法 func (c Circle) getArea() float64 { //c.radius 即为 Circle 类型对象中的属性 return 3.14 * c.radius * c.radius }
杨辉三角的实现以下:
//行数 const LINES int = 10 // 杨辉三角 func PascalTriangle() { nums := []int{} for i := 0; i < LINES; i++ { //补空白 for j := 0; j < (LINES - i); j++ { fmt.Print(" ") } for j := 0; j < (i + 1); j++ { var length = len(nums) var value int if j == 0 || j == i { value = 1 } else { value = nums[length-i] + nums[length-i-1] } nums = append(nums, value) fmt.Print(value, " ") } fmt.Println("") } }
变量是一种使用方便的占位符,用于引用计算机内存地址。
Go语言的取地址符是&,放到一个变量前使用就会返回相应变量的内存地址。
指针变量指向了一个值的内存地址。
指针声明格式以下:var var_name *var-type
var-type为指针类型,var_name为指针变量名,* 号用于指定变量是做为一个指针。
var ip *int /* 指向整型*/ var fp *float32 /* 指向浮点型 */
指针使用流程:
A、定义指针变量。
B、为指针变量赋值。
C、访问指针变量中指向地址的值。
在指针类型前面加上*号(前缀)来获取指针所指向的内容。
package main import "fmt" func main() { var a int= 20 /* 声明实际变量 */ var ip *int /* 声明指针变量 */ ip = &a /* 指针变量的存储地址 */ fmt.Printf("a 变量的地址是: %x\n", &a ) /* 指针变量的存储地址 */ fmt.Printf("ip 变量储存的指针地址: %x\n", ip ) /* 使用指针访问值 */ fmt.Printf("*ip 变量的值: %d\n", *ip ) }
当一个指针被定义后没有分配到任何变量时,值为nil。
nil指针也称空指针。
nil在概念上和其它语言的null、None、nil、NULL同样,都指代零值或空值。
一个指针变量一般缩写为ptr。
package main import "fmt" func main() { var ptr *int fmt.Printf("ptr 的值为 : %x\n", ptr ) }
整型指针数组声明以下:var ptr [MAX]*int;
ptr 为整型指针数组。
package main import "fmt" const MAX int = 3 func main() { a := []int{10,100,200} var i int var ptr [MAX]*int; for i = 0; i < MAX; i++ { ptr[i] = &a[i] /* 整数地址赋值给指针数组 */ } for i = 0; i < MAX; i++ { fmt.Printf("a[%d] = %d\n", i,*ptr[i] ) } }
若是一个指针变量存放的又是另外一个指针变量的地址,则称这个指针变量为指向指针的指针变量。
当定义一个指向指针的指针变量时,第一个指针存放第二个指针的地址,第二个指针存放变量的地址:
指向指针的指针变量声明格式以下:var ptr **int;
访问指向指针的指针变量值须要使用两个*号,以下所示:
package main import "fmt" func main() { var a int var ptr *int var pptr **int a = 3000 /* 指针 ptr 地址 */ ptr = &a /* 指向指针 ptr 地址 */ pptr = &ptr /* 获取 pptr 的值 */ fmt.Printf("变量 a = %d\n", a ) fmt.Printf("指针变量 *ptr = %d\n", *ptr ) fmt.Printf("指向指针的指针变量 **pptr = %d\n", **pptr) }
Go语言容许向函数传递指针,只须要在函数定义的参数上设置为指针类型便可。
package main import "fmt" func main() { /* 定义局部变量 */ var a int = 100 var b int= 200 fmt.Printf("交换前 a 的值 : %d\n", a ) fmt.Printf("交换前 b 的值 : %d\n", b ) /* 调用函数用于交换值 * &a 指向 a 变量的地址 * &b 指向 b 变量的地址 */ swap(&a, &b); fmt.Printf("交换后 a 的值 : %d\n", a ) fmt.Printf("交换后 b 的值 : %d\n", b ) } func swap(x *int, y *int) { var temp int temp = *x /* 保存 x 地址的值 */ *x = *y /* 将 y 赋值给 x */ *y = temp /* 将 temp 赋值给 y */ }