一小时带你了解Golang的基础语法

138 阅读1分钟

基本程序结构

package main//包,表明代码所在的模块

import "fmt"//引入代码依赖
//功能实现
func main() {
   fmt.Println("Hello, GoLang!")
}

应用程序入口

  1. 必须是main包:package main
  2. 必须是main方法:func main()
  3. 文件名不一定是main.go
  4. 与其他主要编程语言的差异
    1. Go中的main函数不支持任何返回值,只能通过os.Exit来返回状态
    2. main函数不支持传入参数,在程序中直接通过os.Args获取命令行参数

编写测试程序

  1. 源码文件以_test结尾:xxx_test.go
  2. 测试方式以Test开头:func TestXXX(t *testing.T){...}
package try_test

import "testing"

func TestFirstTry(t *testing.T) {
   t.Log("My first try!")
}

变量赋值

  1. 赋值可以进行自动类型推断
  2. 在一个赋值语句中可以对多个变量进行同时赋值

赋值操作

  1. [var][变量名][类型][=][值],var name int = 1
  2. [变量名][:][=][值],a := 1
  3. 多变量赋值,var ( a int = 1 b int = 2 )
  4. 交换操作,a, b = b, a

常量定义

快速设置连续值

package try_test

import "testing"

// 设置连续值
const (
   Monday    = iota + 1 //1
   Tuesday              //2
   Wednesday            //3
   Thursday             //4
   Friday               //5
   Saturday             //6
   sunday               //7
)

// 设置位运算值
const (
   Readable   = 1 << iota //00000001
   Writeable              //00000010
   Executable             //0000100
)

func TestConstant(t *testing.T) {
   t.Log(Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, sunday) //1 2 3 4 5 6 7
}

func TestConstant1(t *testing.T) {
   t.Log(Readable, Writeable, Executable) // 1 2 4
}

基本数据类型

  • 布尔型:bool
  • 字符型:string
  • 整型:int、int8、int16、int32、int64
  • 无符号整型:uint、uint8、uint16、uint32、uint64、uintptr
  • 字节型:byte(uint8的别名)
  • Unicode编码值:rune(int32)
  • 浮点型:float32、float64
  • 复数型:complex64、complex128

类型转换

  1. Go语言不允许隐式类型转换
  2. 别名和原有类型也不能进行隐式类型转换

image.png

image.png

类型的预定义值

  1. math.MaxInt64
  2. math.MaxFloat64
  3. math.MaxUint32

指针类型

  1. 不支持指针运算
  2. string是只类型,其默认的初始化值是空字符串,而不是nil

image.png

image.png

算术运算符

A = 10, B = 20

标题描述实例
+相加A + B 输出结果为30
-相减A - B 输出结果为-10
*相乘A * B 输出结果为200
/相除B / A 输出结果为2
%求余B % A 输出结果为0
++自增A++ 输出结果为11
--自减A-- 输出结果为9

注意:Go语言没有前置的++,--

比较运算符

用==比较数组

  • 相同维数且含有相同个数元素的数组才可以比较
  • 每个元素相同的才相等

image.png

位运算符

&^按位置零,如果右边为1,则为0,如果右边为0,则为左边的数,如

1 &^ 0 -- 1
1 &^ 1 -- 0
0 &^ 1 -- 0
0 &^ 0 -- 0

循环

image.png

if条件

基本结构

image.png

支持变量赋值,通常可以用来对方法执行的错误进行判断

func TestIfMultiSec(t *testing.T) {
   if a := 1 == 1; a {
      t.Log("a == 1")
   } else {
      t.Log("a == others")
   }
}
func TestIfMultiSec(t *testing.T) {
   if v, err := SomeFun(); err == nil {
      t.Log("a == 1")
   } else {
      t.Log("error!")
   }
}

switch条件

  1. 条件表达式不限制为常量或者整数
  2. 单个case中,可以出现多个结果选项,使用逗号分隔,命中一个即可
  3. 与C语言规则相反,Go语言不需要用break来明确退出一个case
  4. 可以不设定switch之后的条件表达式,整个switch结构与多个if...else..的逻辑作用等同

image.png

如下等同与if...else...

image.png

数组的声明

// 定义数组
func TestArray(t *testing.T) {
   var arr0 [3]int                                    //一维初始化
   arr1 := [4]int{1, 2, 3, 4}                         //固定长度初始化
   arr2 := [...]int{1, 2, 3, 4, 5, 6}                 // 非固定长度初始化
   arr3 := [3][3]int{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}} //二维数组固定长度舒适化
   t.Log(arr0, arr1, arr2, arr3)                      //  [0 0 0] [1 2 3 4] [1 2 3 4 5 6] [[1 2 3] [4 5 6] [7 8 9]]
}

// 遍历数组
func TestArrayTravel(t *testing.T) {
   arr := [...]int{1, 3, 4, 5}
   for i := 0; i < len(arr); i++ {
      t.Log(arr[i])
   }
   //for-each
   for idx, e := range arr {
      t.Log(idx, e)
   }
   //不输出index
   for _, e := range arr {
      t.Log(e)
   }
}

数组截取

截取规则:array[开始索引(包含), 结束索引(不包含)]

// 数组截取
func TestArraySplit(t *testing.T) {
   arr := [...]int{1, 2, 3, 4, 5}
   t.Log(arr[1:2])        //[2]
   t.Log(arr[1:3])        //[2 3]
   t.Log(arr[1:len(arr)]) //[2 3 4 5]
   t.Log(arr[1:])         // [2 3 4 5]
   t.Log(arr[:3])         //[1 2 3]
   t.Log(arr[0:3])        //[1 2 3]
}

切片

内部结构

image.png

声明方式

// 切片声明方式
func TestSliceInit(t *testing.T) {
   var s0 []int
   t.Log(len(s0), cap(s0)) //0 0
   s0 = append(s0, 1)      //填充一个元素
   t.Log(len(s0), cap(s0)) //1 1
   s1 := []int{1, 2, 3, 4}
   t.Log(len(s1), cap(s1)) //4 4
   s2 := make([]int, 3, 5)
   t.Log(len(s2), cap(s2)) //3 5
}

扩容方式

func TestSliceGrowing(t *testing.T) {
   s := []int{}
   for i := 0; i < 10; i++ {
      s = append(s, i) // 会在超过数组元素的时候,创建一个新的空间(空间大小 * 2),然后赋值
      t.Log(len(s), cap(s))
   }
}

运行结果如图所示

image.png

当存储的元素超过cap的时候,会扩容两倍,也就是cap = cap * 2

切片共享存储结构

image.png

func TestSliceShareMemory(t *testing.T) {
   year := []string{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}
   Q2 := year[3:6]
   //cap的大小等于len(year)减去Q2[0]之前的元素的数量
   t.Log(Q2, len(Q2), cap(Q2)) //[Apr May Jun] 3 9
   summer := year[5:8]
   t.Log(summer, len(summer), cap(summer)) //[Jun Jul Aug] 3 7
   summer[0] = "unknow"                    //影响整个共享空间
   t.Log(Q2)                               //[Apr May unknow]
   t.Log(year)                             // [Jan Feb Mar Apr May unknow Jul Aug Sep Oct Nov Dec]
}

数组和切片的区别

  • 容量是否可伸缩:数组容量固定,切片容量可以伸缩
  • 是否可以比较:数组内容可以比较,切片不行

image.png

本文章参考来自Go语言从入门到实战