Spiga

Go学习笔记(一):语法基础1

2020-04-08 11:50:28

1.编写第一个Go程序

首先我们编写一个Hello World程序

package main //包,表明代码所在的模块(包)
import "fmt" //引⼊代码依赖
​
//功能实现
func main() { 
    fmt.Println("Hello World!")
}

应用程序入口

1.必须是 main 包:package main

2.必须是 main ⽅法:func main()

3.⽂件名不⼀定是main.go

main函数的返回值和参数

与其他主要编程语⾔的差异

  • Go 中main函数不⽀持任何返回值
  • 需要通过os.Exit来返回状态
  • 同样main 函数不⽀持传⼊参数 func main(arg []string)
  • 在程序中直接通过os.Args获取命令⾏参数
package main
​
import (
    "fmt"
    "os"
)
​
func main() {
    if len(os.Args) > 1 {
        fmt.Println("Hello World", os.Args[1])
    }
    os.Exit(-1)
}

2. 变量与常量

在开始前先介绍一下go语言如何编写一个测试代码,方便编写测试程序。go语言只要满足下面2点规则就能运行测试

  • 源码⽂件以_test结尾:xxx_test.go
  • 测试⽅法名以Test开头:func TestXXX(t *testing.T) {…}
    接下来我们编写一个Fibonacci 数列来介绍变量的定义
    数列:1, 1, 2, 3, 5, 8, 13, ….
import (
    "testing"
)
​
func TestFibList(t *testing.T) {
    // 1. 变量声明一般方法
    // var a int = 1
    // var b int = 1
    
    // 2. 统一一起声明,注意变量b 去掉了类型定义,系统可以根据赋值自动判断
    // var (
    //  a int = 1
    //  b     = 1
    // )
    
    // 3. 方法3,快捷声明与赋值(推荐)
    a := 1
    b := 1
    t.Log(a)
    for i := 0; i < 5; i++ {
        t.Log(" ", b)
        tmp := a
        a = b
        b = tmp + a
    }
}
在⼀个赋值语句中可以对多个变量进⾏同时赋值。利用go语言这个特性,如果要实现变量的值交换,有更便捷的写法,如下:
func TestExchange(t *testing.T) {
    a := 1
    b := 2
    // 1. 其他语言交换变量需要先用一个临时变量来实现,而go语言可以直接交换
    // tmp := a
    // a = b
    // b = tmp
    
    // 2. go语言的直接赋值语法,实现变量值的交换
    a, b = b, a
    t.Log(a, b)
}

go与其他主要编程语⾔的差异

可快速设置连续值

const ( 
    Monday = iota + 1 
    Tuesday 
    Wednesday 
    Thursday 
    Friday 
    Saturday 
    Sunday
)

下面代码实现快速对常量进行位赋值 1、2、4

const ( 
    Open = 1 << iota 
    Close 
    Pending
)

4.数据类型

go语言支持如下数据类型

类型
bool
string
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
byte // alias for uint8
rune // alias for int32,represents a Unicode code point
float32 float64
complex64 complex128

类型转换

与其他主要编程语⾔的差异

  • Go 语⾔不允许隐式类型转换
  • 别名和原有类型也不能进⾏隐式类型转换

类型的预定义值

  • math.MaxInt64
  • math.MaxFloat64
  • math.MaxUint32

指针类型

与其他主要编程语⾔的差异

  • Go 语⾔不⽀持指针运算
  • string 是值类型,其默认的初始化值为空字符串,⽽不是 nil

其他语言中我们判断string不为空需要判断 str !=null && str != "",而go语言string默认值就是“”, 所以只需要如下代码判断,且默认的长度为0, 其他强类型语言对空的string取长度可能会出现空异常

func TestString(t *testing.T) {
    var s string
    if(s == "") {
        t.Log("*" + s + "*") //初始化零值是“”
    }
    t.Log(len(s))
}

5 运算符

算术运算符

运算符 描述 实例
+ 相加 A + B 输出结果 30
- 相减 A - B 输出结果 -10
* 相乘 A * B 输出结果 200
/ 相除 B / A 输出结果 2
% 求余 B % A 输出结果 0
++ ⾃增 A++ 输出结果 11
-- ⾃减 A-- 输出结果 9

Go 语⾔没有前置的 ++,- -,(++a)

比较运算符

运算符 描述 实例
== 检查两个值是否相等,如果相等返回 True 否则返回 False (A == B) 为 False
!= 检查两个值是否不相等,如果不相等返回 True 否则返回 False (A != B) 为 True
> 检查左边值是否⼤于右边值,如果是返回 True 否则返回 False (A > B) 为 False
< 检查左边值是否⼩于右边值,如果是返回 True 否则返回 False (A < B) 为 True
>= 检查左边值是否⼤于等于右边值,如果是返回 True 否则返回 False (A >= B) 为 False
<= 检查左边值是否⼩于等于右边值,如果是返回 True 否则返回 False (A <= B) 为 True

⽤ == ⽐较数组

  • 相同维数且含有相同个数元素的数组才可以⽐较
  • 每个元素都相同的才相等
func TestCompareArray(t *testing.T) {
    a := [...]int{1, 2, 3, 4}
    b := [...]int{1, 3, 2, 4}
    //  c := [...]int{1, 2, 3, 4, 5}
    d := [...]int{1, 2, 3, 4}
    t.Log(a == b)
    //t.Log(a == c) //数组长度不一致,不能比较
    t.Log(a == d)
}

逻辑运算符

运算符 描述 实例
&& 逻辑 AND 运算符。如果两边的操作数都是 True,则条件 True,否则为 False (A && B) 为 False
逻辑 NOT 运算符。如果条件为 True,则逻辑 NOT 条件 False,否则为 True !(A && B) 为 True

位运算符

运算符 描述 实例
& 按位与运算符"&"是双⽬运算符。其功能是参与运算的两数各对应的⼆进位相与 (A & B) 结果为 12, ⼆进制为 0000 1100
按位或运算符"
^ 按位异或运算符"^"是双⽬运算符。其功能是参与运算的两数各对应的⼆进位相异或,当两对应的⼆进位相异时,结果为1。(A ^ B) 结果为 49, ⼆进制为 0011 0001 (A ^ B) 结果为 49, ⼆进制为 0011 0001
<< 左移运算符”<<"是双⽬运算符。左移 n 位就是乘以 2 的 n 次⽅。其功能把"<<"左边的运算数的各⼆进位全部左移若⼲位,由"<<"右边的数指定移动的位数,⾼位丢弃,低位补 A << 2 结果为 240 ,⼆进制为 1111 0000
>> 右移运算符”>>"是双⽬运算符。右移 n 位就是除以 2 的 n 次⽅。其功能是把">>"左边的运算数的各⼆进位全部右移若⼲位,">>"右边的数指定移动的位数 A >> 2 结果为 15 ,⼆进制为 0000 1111

与其他主要编程语⾔的差异

&^ 按位置零

1 &^ 0 -- 1

1 &^ 1 -- 0

0 &^ 1 -- 0

0 &^ 0 -- 0

&^ 当右边为0是,保留左边的值;当右边为1时,结果为0。这种运算可以用于清除权限。如下代码:

const (
        Readable = 1 << iota
        Writable
        Executable
)
func TestBitClear(t *testing.T) {
        a := 7 //0111
        a = a &^ Readable
        a = a &^ Executable
        t.Log(a&Readable == Readable, a&Writable == Writable, a&Executable == Executable)
}

6、结构化程序

for

Go 语⾔仅⽀持循环关键字 for

n := 0
for n < 5 { 
	n++ 
	fmt.Println(n)
}

if

  • condition 表达式结果必须为布尔
  • ⽀持变量赋值
if  var declaration;  condition{    
	//code to be executed if condition is true
}

switch

  • 条件表达式不限制为常量或者整数;
  • 单个 case 中,可以出现多个结果选项, 使⽤逗号分隔;
  • 与 C 语⾔等规则相反,Go 语⾔不需要⽤break来明确退出⼀个 case;
  • 可以不设定 switch 之后的条件表达式,在此种情况下,整个 switch 结构与多个 if…else… 的逻辑作⽤等同
switch os := runtime.GOOS; os {
	case "darwin": 
		fmt.Println("OS X.") 
		//break 
	case "linux": 
		fmt.Println("Linux.") 
	default: 
		// freebsd, openbsd, 
		// plan9, windows... 
		fmt.Printf("%s.", os)
}


switch {  
	case 0 <= Num && Num <= 3:  
		fmt.Printf("0-3")  
	case 4 <= Num && Num <= 6:  
		fmt.Printf("4-6")  
	case 7 <= Num && Num <= 9:  
		fmt.Printf("7-9")
}