Go语言1-数据类型

本文介绍GO语言开发环境和基本数据类型

开始学习GO,主要原因是现在使用的一些组件如Docker,K8s,Etcd都是用GO开发的,希望能对使用的东西多一些了解,读懂简单的源码。

作为“未来的服务端语言”,代码优雅,天生并发,可以直接在机器上运行,支持多方范式编程等等很多优点。不废话了,开始吧。

一、GO开发环境

windows

  1. 下载安装,安装到默认路径。安装完成后默认会在环境变量 Path 后添加 Go 安装目录下的 bin 目录 C:\Go\bin\,并添加环境变量 GOROOT,值为 Go 安装根目录 C:\Go\。安装后,在cmd中运行go env测试。
  2. 配置
    安装go,安装sublime,安装插件gosublime
    插件user-setting
    bash { "env":{ "GOPATH":"E:/GO", "GOROOT":"C:/Program Files (x86)/Go" } }

Linux

wget https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
sudo tar -xzf go1.8.3.linux-amd64.tar.gz -C /usr/local 

# vim /etc/profiles
export GOROOT=/usr/local/go
export GOBIN=$GOROOT/bin
export PATH=$PATH:$GOBIN
export GOPATH=$HOME/gopath (可选设置)

source /etc/profiles

go 程序结构

结构和java差不多,主要是这些:声明包,导入包,函数,变量,语句,注释。但也有区别,比如main包作为执行程序的入口,导入的包未使用会编译出错等。

编译执行

比如有文件hello.go

go build hello.go # 编译成可执行文件
go run hello.go # 运行

二、数据结构

go 中都是大写字母开头作为模块的使用。
函数可以没有参数或接受多个参数。当两个或多个连续的函数命名参数是同一类型,则除了最后一个类型之外,其他都可以省略。函数可以返回任意数量的返回值。

package main

import "fmt"

func add(x, y int) int {
	return x + y
}

func main() {
	fmt.Println(add(42, 13))
}
package main

import "fmt"

func swap(x, y string) (string, string) {
	return y, x
}

func main() {
	a, b := swap("hello", "world")
	fmt.Println(a, b)
}

命名返回值
Go 的返回值可以被命名,并且就像在函数体开头声明的变量那样使用。

返回值的名称应当具有一定的意义,可以作为文档使用。没有参数的 return 语句返回各个返回变量的当前值。这种用法被称作“裸”返回。

2.1 变量

var 语句定义了一个变量的列表;跟函数的参数列表一样,类型在后面。就像在这个例子中看到的一样, var 语句可以定义在包或函数级别。

var a, b int = 1, 2 // 多个值声明
var c int // 没初始化,默认为0
d := "short"  // 赋值简写

常量

const s string = "constant"

2.2 循环

for 是go中唯一的循环结构

func main() {
	i :=1
	for i<=3 {
		fmt.Println(i)
		i = i+1
	}
	for j := 7;j <=9 ;j++  {
		fmt.Println(j)
	}
	for{// 不带条件会一直循环
		fmt.Println("loop")
		break
	}
}

2.3分支

if 7%2 == 0{
		fmt.Println("7 is even")
	}else {
		fmt.Println("7 is odd")
	}
	if num := 9; num <0 {
		fmt.Println("is negative")
	}

Go: 你可以不用圆括号,但需要花括号;go没有三目运算符

func main() {
	i := 2
	fmt.Print("write ", i, " as ")
	switch i {
	case 1:
		fmt.Println("one")
	case 2:
		fmt.Println("two")
	case 3:
		fmt.Println("three")
	}
}

三、数组、切片

3.1 数组声明

var a [5]int // 声明不初始化,默认为0,0,0....
var twoD [2][3]int
array := [5]int{10, 20, 30, 40, 50}
array := [...]int{10, 20, 30, 40, 50} // 容量由初始化时确定
array := [5]int{1: 10, 2: 20}   // [0 10 20 0 0]

len(a), a[3]

3.2 使用数组

相同长度和类型的数组才能赋值。

var array1 [5]string
array2 := [5]string{"Red","Blue", "Green", "Yello", "Pink"}
array1 = array2 // 复制
array1[1] = "Orther Color" // 修改
// for 遍历 arr
for index, value := range array2{
	fmt.Printf("arr[%d]=%s\n", index, value)
}

3.3 切片

切片是一种数据结构,这种数据结构便于使用和管理数据集合。切片是围绕动态数组的概念构建的,可以按需自动增长和缩小。切片的动态增长是通过内置函数 append 来实现的.

切片有3个字段: 指针,长度,容量。

// 其长度和容量都是 5 个元素
 slice1 := make([]string, 5)
// 其长度为 3 个元素,容量为 5 个元素
 slice2 := make([]int, 3, 5)
 
// 另一种直接初始化的方式创建切片,和数组不同的是,使用[]
// 其长度和容量都是 5 个元素
slice := []string{"Red", "Blue", "Green", "Yellow", "Pink"}
// 其长度和容量都是 3 个元素
 slice := []int{10, 20, 30}
 // 使用空字符串初始化第 100 个元素 
 slice := []string{99: ""}

//  创建 nil 整型切片
var slice []int
// 使用 make 创建空的整型切片
slice := make([]int, 0)
// 使用切片字面量创建空的整型切片
 slice := []int{}

注意:如果在[]运算符里指定了一个值,那么创建的就是数组而不是切片。只有不指定值 的时候,才会创建切片

相对于数组而言,使用切片的一个好处是,可以按需增加切片的容量。Go 语言内置的 append 函数会处理增加长度时的所有操作细节。
函数 append 会智能地处理底层数组的容量增长。在切片的容量小于 1000 个元素时,总是 会成倍地增加容量。一旦元素个数超过 1000,容量的增长因子会设为 1.25,也就是会每次增加 25% 的容量

slice := []int{10, 20, 30, 40, 50}
newSlice := slice[1:3]
newSlice = append(newSlice,60)
fmt.Println(newSlice)//[20 30 60]

alice := slice[2:3:4]// index=2,lenth=3-2;cap=4-2

// 创建两个切片,并分别用两个整数进行初始化 s1 := []int{1, 2}
s2 := []int{3, 4}
// 将两个切片追加在一起,并显示结果 
fmt.Printf("%v\n", append(s1, s2...))//[1 2 3 4]

四、映射

映射是一种数据结构,用于存储一系列无序的键值对。如下图所示,键通过散列函数得到散列值,找到对应存储桶,所以它的存储并不是有序的。

其实说白了,映射这种结果,在java中叫map,在python中对应字典。使用简单,算法经典。

示例

package main

import (
	"fmt"
)

func main() {
	// 创建map,string:int
	//dict := make(map[string]int)
	// 创建map,string:string
	dict := map[string]string{"name":"thoreau","age": "27"}

	// 添加修改
	dict["addr"] = "0.0.0.0"
	// 判断key是否存在
	value, exists := dict["addr"]
	if exists {
		fmt.Println(value)
	}
	// delete
	delete(dict,"addr")
	// 遍历
	for key, value := range dict {
		fmt.Printf("Key: %s ,Value: %s \n",key,value)
	}
}

上面是一个完整的示例,包括初始化、修改、添加、删除和遍历等常用操作。


待丰富完善

CONTENTS