Go语言开发(二)、Go语言基础

Go语言开发(二)、Go语言基础

一、Go语言程序结构

Go语言程序基本结构如下:
A、包声明
B、引入包
C、函数
D、变量
E、语句 & 表达式
F、注释

package main //包声明

import "fmt" //引入包

func main(){ //main函数
   //打印Hello World
   fmt.Print("Hello World!")
}

二、Go语言基础语法

1、Go语言标记

Go语言程序由多个标记组成,可以是关键字、标识符、常量、字符串、符号。
fmt.Println("Hello, World!")语句由6个标记组成:

fmt
.
Println
(
"Hello, World!"
)

2、行分隔符

在Go语言程序中,一行代表一个语句结束。每个语句不需要像C家族中的其它语言一样以分号;结尾。
如果打算将多个语句写在同一行,则必须使用;人为区分,但在实际开发中不推荐。

fmt.Println("Hello, World!")
fmt.Println("Hello, Go!")

3、注释

注释不会被编译,每一个包应该有相关注释。
单行注释是最常见的注释形式,可以在任何地方使用以 // 开头的单行注释。 多行注释也叫块注释,均已以 / 开头,并以 / 结尾。

//打印hello world
   /*
   It print to console a string
   */

4、标识符

标识符用来命名变量、类型等程序实体。标识符是由一个或是多个字母(A~Z和a~z)数字(0~9)、下划线_组成的序列,但第一个字符必须是字母或下划线而不能是数字。无效的标识符如下:
1ab(以数字开头)
case(Go语言的关键字)
a+b(运算符是不允许的)

5、关键字

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
程序一般由关键字、常量、变量、运算符、类型和函数组成。
程序中可能会使用到分隔符:括号 (),中括号 [] 和大括号 {}。
程序中可能会使用到标点符号:.、,、;、: 和 …。

6、空格

Go语言中变量的声明必须使用空格隔开,如:
var age int;
语句中适当使用空格能让程序看易阅读。
无空格:
fruit=apples+oranges;
在变量与运算符间加入空格,程序看起来更加美观,如:
fruit = apples + oranges;

7、可见性规则

Go语言中,使用大小写来决定常量、变量、类型、接口、结构或函数是否可以被外部包所调用。
函数名首字母小写即为private :
func getId() {}
函数名首字母大写即为public :
func Printf() {}

8、Package

Go语言程序通过package来组织,只有package名称为main的包可以包含main函数。
一个可执行程序有且仅有一个main包。
通过import关键字来导入其他非main包。
可以通过import关键字单个导入:

    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语言数据类型

在Go编程语言中,数据类型用于声明函数和变量。
数据类型是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存。

1、bool

布尔型的值只可以是常量true或者false。
var b bool = true

2、数字类型

整型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:无符号整型,用于存放一个指针

3、字符串类型

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

4、派生类型

派生类型包括:
A、指针类型(Pointer)
B、数组类型
C、结构化类型(struct)
D、Channel 类型
E、函数类型
F、切片类型
G、接口类型(interface)
H、Map 类型

四、Go语言变量

1、Go语言变量简介

变量是计算机语言中能储存计算结果或能表示值的抽象概念。变量可以通过变量名访问。
Go 语言变量名由字母、数字、下划线组成,其中首个字母不能为数字。

2、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

3、Go语言多变量声明

//类型相同多个变量, 非全局变量
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"

4、值类型和引用类型

int、float、bool、string等基本类型都属于值类型,值类型的变量直接指向存在内存中的值。
当使用等号=将一个变量的值赋值给另一个变量时,如:j = i,实际上是在内存中将i的值进行拷贝。
可以通过&i来获取变量i的内存地址,例如0xf840000040(地址随机)。值类型的变量的值存储在栈中。
内存地址会根据机器的不同而有所不同,相同的程序在不同的机器上执行后也会有不同的内存地址。因为每台机器可能有不同的存储器布局,并且位置分配也可能不同。
更复杂的数据通常会需要使用多个字,一般使用引用类型保存。
一个引用类型的变量r1存储的是r1的值所在的内存地址(数字),或内存地址中第一个字所在的位置。
同一个引用类型的指针指向的多个字可以是在连续的内存地址中(内存布局是连续的),也可以将这些字分散存放在内存中,每个字都指示了下一个字所在的内存地址。
当使用赋值语句r2 = r1时,只有引用(地址)被复制。
如果r1的值被改变,r1的所有引用都会指向被修改后的内容。

五、Go语言变量作用域

1、Go语言变量作用域简介

作用域为已声明标识符所表示的常量、类型、变量、函数或包在源代码中的作用范围。
Go语言中变量可以在三个地方声明:
A、函数内定义的变量称为局部变量
B、函数外定义的变量称为全局变量
C、函数定义中的变量称为形式参数

2、局部变量

在函数体内声明的变量为局部变量,其作用域只在函数体内,参数和返回值变量也是局部变量。

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)
}

3、全局变量

在函数体外声明的变量为全局变量,全局变量可以在整个包甚至外部包(被导出后)使用。

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)
}

4、形式参数

形式参数会作为函数的局部变量来使用。

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;
}

5、局部和全局变量的初始化

不同类型的局部和全局变量默认值为:
int 0
float32 0
pointer nil

六、Go语言常量

1、Go语言常量

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

2、Go语言常量声明

常量的定义格式:
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)
}

3、Go语言枚举

常量可以用作枚举:

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)
}

4、iota

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语言运算符

1、Go语言运算符简介

运算符用于在程序运行时执行数学或逻辑运算。Go语言内置的运算符有:
A、算术运算符
B、关系运算符
C、逻辑运算符
D、位运算符
E、赋值运算符
F、其它运算符

2、算术运算符

+    相加     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)
}

3、关系运算符

==:检查两个值是否相等,如果相等返回 True 否则返回 False。
!=:检查两个值是否不相等,如果不相等返回 True 否则返回 False。
>:检查左边值是否大于右边值,如果是返回 True 否则返回 False。
<:检查左边值是否小于右边值,如果是返回 True 否则返回 False。
>=:检查左边值是否大于等于右边值,如果是返回 True 否则返回 False。
<=:检查左边值是否小于等于右边值,如果是返回 True 否则返回 False。

4、逻辑运算符

&&:逻辑AND运算符。 如果两边的操作数都是True,则条件True,否则为False。
||:逻辑OR运算符。 如果两边的操作数有一个True,则条件True,否则为False。
!:逻辑NOT运算符。 如果条件为True,则逻辑NOT条件False,否则为True。

5、位运算符

&:按位与运算符"&"是双目运算符,功能是参与运算的两数各对应的二进位进行相与。
|:按位或运算符"|"是双目运算符,功能是参与运算的两数各对应的二进位进行相或。
^:按位异或运算符"^"是双目运算符,功能是参与运算的两数各对应的二进位进行相异或,当两对应的二进位相异时,结果为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 )
}

6、赋值运算符

=:简单的赋值运算符,将一个表达式的值赋给一个左值
+=:相加后再赋值
-=:相减后再赋值
*=:相乘后再赋值
/=:相除后再赋值
%=:求余后再赋值
<<=:左移后赋值
>>=:右移后赋值
&=:右移后赋值
^=:按位异或后赋值
|=:按位或后赋值

赋值运算符实例:

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 )

}

7、其它运算符

&:返回变量存储地址
*:指针变量

实例:

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);
}

8、运算符优先级

有些运算符拥有较高的优先级,二元运算符的运算方向均是从左至右。
优先级 运算符

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)
}

八、Go语言条件语句

1、条件语句简介

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

2、if语句

if语句由一个布尔表达式后紧跟一个或多个语句组成。
Go编程语言中if语句的语法如下:

if 布尔表达式 {
   /* 在布尔表达式为 true 时执行 */}

If在布尔表达式为true时,其后紧跟的语句块执行,如果为false则不执行。

3、if...else语句

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")
   }
}

4、if嵌套语句

if或else if语句中嵌入一个或多个if或else if语句。

5、switch语句

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("未知型")
}

6、select语句

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")
   }
}

九、Go语言循环语句

1、循环语句简介

实际问题中有许多具有规律性的重复操作,因此在程序中就需要重复执行某些语句。
循环语句的结构如下:

2、for循环

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)
   }
}

3、循环嵌套

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);
      }
   }
}

4、循环控制语句

循环控制语句可以控制循环体内语句的执行过程。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++
}

5、无限循环

如果循环中条件语句永远不为false,则会进行无限循环。可以通过for循环语句中只设置一个条件表达式来实现无限循环。

for true{
   fmt.Printf("这是无限循环。\n");
}

十、Go语言函数

1、Go语言函数简介

函数是基本的代码块,用于执行一个任务。
Go语言最少有个main()函数。
可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务。
函数声明告诉编译器函数的名称、返回类型和参数。
Go语言标准库提供了多种可用的内置的函数。例如,len()函数可以接受不同类型参数并返回该类型的长度。如果传入的是字符串则返回字符串的长度,如果传入的是数组,则返回数组中包含的元素个数。

2、函数定义

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
}

3、函数调用

当创建函数时,定义函数需要做什么,通过调用该函数来执行指定任务。
调用函数,向函数传递参数,并返回值,例如:

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
}

4、函数返回值

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)
}

5、函数参数

函数如果使用参数,参数变量称为函数的形参。
调用函数,可以通过两种方式来传递参数:
A、值传递
值传递是指在调用函数时将实际参数复制一份传递到函数中,在函数中如果对参数进行修改,将不会影响到实际参数。
B、引用传递
引用传递是指在调用函数时将实际参数的地址传递到函数中,在函数中对参数所进行的修改,将影响到实际参数。
默认情况下,Go 语言使用的是值传递,即在调用过程中不会影响到实际参数。

6、函数用法

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语言指针

1、Go语言指针的定义

变量是一种使用方便的占位符,用于引用计算机内存地址。
Go语言的取地址符是&,放到一个变量前使用就会返回相应变量的内存地址。
指针变量指向了一个值的内存地址。
指针声明格式如下:
var var_name *var-type
var-type为指针类型,var_name为指针变量名,* 号用于指定变量是作为一个指针。

var ip *int        /* 指向整型*/
var fp *float32    /* 指向浮点型 */

2、Go语言指针的使用

指针使用流程:
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 )
}

3、Go语言空指针

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

package main

import "fmt"

func main() {
   var  ptr *int

   fmt.Printf("ptr 的值为 : %x\n", ptr  )
}

4、Go语言指针数组

整型指针数组声明如下:
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] )
   }
}

5、Go语言二级指针

如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量。
当定义一个指向指针的指针变量时,第一个指针存放第二个指针的地址,第二个指针存放变量的地址:

指向指针的指针变量声明格式如下:
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)
}

6、Go语言指针参数

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 */
}

原文地址:http://blog.51cto.com/9291927/2127825

时间: 2024-10-10 07:53:00

Go语言开发(二)、Go语言基础的相关文章

Java架构师成长之道之RabbitMQ开发与运维-基础篇(CSDN版)

Java架构师成长之道之RabbitMQ开发与运维-基础篇(CSDN版) Java架构师成长之道 消息中间件概述 消息是指在不同语言实现的应用间传递的数据,消息可以是文本字符串.JSON,也可以是复杂的内前对象. 消息中间件是指利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通讯来进行分布式系统集成. 通过提供消息传递和消息排队模型,使得在分布式环境下扩展进程间的通讯. 消息中间件一般有两种传递模式:点对点模式和发布/订阅模式. 点对点是基于队列的,消息生产者将消息发送到消息队列,

嵌入式linux C++语言(二)——C++对C语言基础语法的扩展

嵌入式linux C++语言(二)--C++对C语言基础语法的扩展 C++是基于C语言扩展发展而来的面向对象的程序设计语言,本文将主要讨论C++语言基于C语言扩展的方面. 一.类型增强 1.类型检查更严格 在C语言中: const int a = 100; int *p = &a; 在C++语言中: const int a = 100;//必须在定义的时候初始化 const int *p = &a; 在C++语言中不能隐式转换数据类型. error: invalid conversion

程序设计C语言二级考试教程 Java基础视频教程 安卓软件开发教程 Unity3D游戏制作入门教程

热门推荐电脑办公计算机基础知识教程 Excel2010基础教程 Word2010基础教程 PPT2010基础教程 五笔打字视频教程 Excel函数应用教程 Excel VBA基础教程 WPS2013表格教程 更多>平面设计PhotoshopCS5教程 CorelDRAW X5视频教程 Photoshop商业修图教程 Illustrator CS6视频教程 更多>室内设计3Dsmax2012教程 效果图实例提高教程 室内设计实战教程 欧式效果图制作实例教程 AutoCAD2014室内设计 Aut

Swift语言指南(二)--语言基础之注释和分号

注释 通过注释向自己的代码中注入不可执行的文本,作为你自己的笔记或提示.Swift编译器运行时会忽略注释. Swift的注释与C语言极其相似,单行注释以两个反斜线开头: //这是一行注释 多行注释以/*开始,以*/结束: ? 1 2 3 <span style="color: rgb(0, 128, 0);">/* 这也是一条注释, 但跨越多行 */ </span> 与 C 语言的多行注释有所不同的是,Swift 的多行注释可以嵌套在其他多行注释内部.写法是在一

iOS开发系列--C语言之基础知识

概览 当前移动开发的趋势已经势不可挡,这个系列希望浅谈一下个人对IOS开发的一些见解,这个IOS系列计划从几个角度去说IOS开发: C语言 OC基础 IOS开发(iphone/ipad) Swift 这么看下去还有大量的内容需要持续补充,但是今天我们从最基础的C语言开始,C语言部分我将分成几个章节去说,今天我们简单看一下C的一些基础知识,更高级的内容我将放到后面的文章中. 今天基础知识分为以下几点内容(注意:循环.条件语句在此不再赘述): Hello World 运行过程 数据类型 运算符 常用

李洪强iOS开发之零基础学习iOS开发【02-C语言】03-关键字、标识符、注释

上一讲中已经创建了第一个C语言程序,知道了C程序是由函数构成的,这讲继续学习C语言的一些基本语法.C语言属于一门高级语言,其实,所有的高级语言的基本语法组成部分都是一样的,只是表现形式不太一样.就好像亚洲人和非洲人,大家都有人类的结构:2只手.2只脚.1个头,只是他们外表不太一样,比如肤色.脸型.因此,你掌握好了一门高级语言,再去学习其他高级语言,那是相当快的.而且,很多其他高级语言,比如后面要学习的Objective-C,都是基于C语言.从C语言衍生出来的,好好学习C语言吧,绝对不吃亏. 一.

简单的入门Android开发和Java语言基础[图]

简单的入门Android开发和Java语言基础[图]前言:去年年底到今年年初,我做过简单的智能家居,也实现过一些简单的直连和远程的智能家居.于是就将最简单的通信发布出来:智能家居简单实现-使用ESP8266简单实现和APP通讯由于这方面的资料少之又少,所以阅读量飙升的很快.也有很多人加了好友问我问题.通过问题我发现,很多都是学硬件的.或是做智能家居方面的学生,基本都不会 Android 开发的.问也有很多问我怎么学 Android 开发的.很多的人认知还是停留在学习这种软件开发技术需要去培训机构

Go语言开发(十二)、Go语言常用标准库二

Go语言开发(十二).Go语言常用标准库二 一.os 1.os简介 os 包提供了不依赖平台的操作系统函数接口,设计像Unix风格,但错误处理是go风格,当os包使用时,如果失败后返回错误类型而不是错误数量. 2.os常用接口 func Hostname() (name string, err error) // Hostname返回内核提供的主机名 func Environ() []string // Environ返回表示环境变量的格式为"key=value"的字符串的切片拷贝 f

Go语言开发(二十)、GoStub测试框架

Go语言开发(二十).GoStub测试框架 一.GoStub简介 GoStub是一款轻量级的单元测试框架,接口友好,可以对全局变量.函数或过程进行打桩.GoStub安装:go get github.com/prashantv/gostub 二.GoStub常用方法 gostub用于在测试时打桩变量,一旦测试运行时,重置原来的值. type Stubs struct { // stubs is a map from the variable pointer (being stubbed) to t