Go语言基础

Posted 想考北航的小刺猬

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go语言基础相关的知识,希望对你有一定的参考价值。

go语言由package构成,go语言的实现使用传统的编译链接模式产生可执行文件。
go语言的特色:

  1. 支持环境采纳模式,例子就是不需声明变量类型,编译器会自动根据赋值的类型而采用相应的类型。
  2. 编译时间短
  3. 内置并行的支持:轻量级的进程、channel、select语句
  4. 支持接口和类型的嵌入
  5. 不需要外部依赖产生静态链接的本地二级制文件

Keyword

Basic

Package

每个go程序都是由packages组成,程序在package main中开始运行。
一般来说包名和导入路径的最后一个元素相同,例如"math/rand"中,就是导入rand包。

package main

import (
	"fmt"
	"math/rand"
	"time"
)
//设置随机数种子,根据当前时间,来产生不同的随机数。如果不设置种子,那么由于每次程序被执行的环境是确定的,所以每次运行程序得到的结果是一样的
func main() 
	//rand.Seed(time.Now().UnixNano())
	fmt.Println("My favorite number is",rand.Intn(100))
	fmt.Println("My favorite number is",rand.Intn(100))


import

将imports组合到括号中,分解导入语句。

import(
	"fmt"
	"math"
)

//也可以写成多导入形式,但分解导入是一种比较好的形式
import "fmt"
import "math"

Exported names

首字母大写的名字是Exported names,也就是可以被外部调用的,导入一个包的时候可以只参考Exported names,非输出名字不会被包外访问。

package main

import (
	"fmt"
	"math"
)

func main() 
	fmt.Println(math.Pi)

Function

  • 一个函数可以携带0个或者多个参数。
  • 类型在变量名之后,返回值类型也位于函数名后面,例如func add1(x, y int) int中的第二个int。同一类型变量可以省略前面的变量类型。
  • 函数也可以返回多个返回值。
  • 返回值可以是指定的,如split中的函数返回值声明处(x, y int),制定了x和y为返回值,在函数体内部即可用return结尾,成为裸返回
package main

import "fmt"

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

func add1(x, y int) int 
	return x + y

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

func split(sum int) (x, y int) 
	x = sum * 4 / 9
	y = sum - x
	return


func main() 
	fmt.Println(add(42, 13))

Variables

  • var语句声明了一个变量列表,一个也可以,类型放在最后
  • var可以在包级别或者函数级别
  • var声明每个变量可以包含初始化值,初始化值出现,类型可以被省略,变量将会用初始化值的类型
  • 函数内部短变量赋值 " := ",隐含类型的变量声明。函数外部不可用
package main

import "fmt"

var c, python, java bool
var i, j int = 1, 2

func main() 
	var i int
	k := 1
	fmt.Println(i, c, python, java, k)

Basic types

  • bool
  • string
  • int int8 int16 int32 int64
  • uint uint8 uint16 uint32 uint64 uintptr
  • byte //uint8的别名
  • rune //int32的别名,表示一个unicode代码指针
  • float32 float64
  • complex64 complex128

Type conversions

package main

import (
	"fmt"
	"math"
)

func main() 
	var x, y int = 3, 4
	var f float64 = math.Sqrt(float64(x*x + y*y))
	var z uint = uint(f)
	fmt.Println(x, y, z)

var i int
j := i // j is an int

Constants

常量声明const关键字,常量不能用:=来声明和赋值。

format:const identifier [type] = value //type可以省略

const Pi = 3.14

const(
	a = "abc"
	b = len(a)
	c = unsafe.Sizeof(a)
)

iota常量可以被编译器修改的常量,iota在const关键字出现的时候被置为0,const中每增加一行将使iota计数一次。

流控制语句

For

初始值可以不在三个组件中出现

package main

import "fmt"

func main() 
	sum := 0
	for i := 0; i < 10; i++ 
		sum += i
	
	fmt.Println(sum)

package main

import "fmt"

func main() 
	sum := 1
	for ; sum < 1000; 
		sum += sum
	
	fmt.Println(sum)

package main

import "fmt"

//go中的while用for替换
func main() 
	sum := 1
	for sum < 1000 
		sum += sum
	
	fmt.Println(sum)

package main

func main() 
	for 
	

If

package main

import (
	"fmt"
	"math"
)

func sqrt(x float64) string 
	if x < 0 
		return sqrt(-x) + "i"
	
	return fmt.Sprint(math.Sqrt(x))


func main() 
	fmt.Println(sqrt(2), sqrt(-4))

Switch

package main

import (
	"fmt"
	"runtime"
)

func main() 
	fmt.Print("Go runs on ")
	switch os := runtime.GOOS; os 
	case "darwin":
		fmt.Println("OS X.")
	case "linux":
		fmt.Println("Linux.")
	default:
		// freebsd, openbsd,
		// plan9, windows...
		fmt.Printf("%s.\\n", os)
	

Defer

推迟执行函数到主程序结束之前

package main

import "fmt"

func main() 
	
	var i = 6
	
	defer fmt.Println(i)

	fmt.Println("hello")

Stacking defers

package main

import "fmt"

func main() 
	fmt.Println("counting")

	for i := 0; i < 10; i++ 
		defer fmt.Println(i)
	

	fmt.Println("done")

Break

  • 用于跳出循环,并开始执行循环之后的语句
  • switch中case执行后跳出
  • 多重循环可以使用标号跳出循环

Continue

  • 跳出本次循环
  • 可以使用标号跳出循环

Goto

  • 跳转到标号处,无条件转移

struct、slice和map

Pointers

声明和C语言差不多,但是不能进行指针的计算。

var p *int
i := 42
p = &i

Struct

type Vertex struct 
	X int
	Y int

func main() 
	v := Vertex1, 2
	v.X = 4
	fmt.Println(v.X)

Struct Literals

type Vertex struct 
	X, Y int


var (
	v1 = Vertex1, 2  // has type Vertex
	v2 = VertexX: 1  // Y:0 is implicit
	v3 = Vertex      // X:0 and Y:0
	p  = &Vertex1, 2 // has type *Vertex
)

Arrays

package main

import "fmt"

func main() 
	var a [2]string
	a[0] = "Hello"
	a[1] = "World"
	fmt.Println(a[0], a[1])
	fmt.Println(a)

	primes := [6]int2, 3, 5, 7, 11, 13
	fmt.Println(primes)

Slices

slice不会存储任何数据,只是一个数组的引用,修改slice的元素会直接修改原位置数据

package main

import "fmt"

func main() 
	primes := [6]int2, 3, 5, 7, 11, 13

	var s []int = primes[1:4]
	fmt.Println(s)

package main

import "fmt"

func main() 
	q := []int2, 3, 5, 7, 11, 13
	fmt.Println(q)

	r := []booltrue, false, true, true, false, true
	fmt.Println(r)

	s := []struct 
		i int
		b bool
	
		2, true,
		3, false,
		5, true,
		7, true,
		11, false,
		13, true,
	
	fmt.Println(s)

cap和len可以计算容量和长度:

fmt.Printf("len=%d cap=%d %v\\n", len(s), cap(s), s)

0值的slice是一个nil,空值

package main

import "fmt"

func main() 
	var s []int
	fmt.Println(s, len(s), cap(s))
	if s == nil 
		fmt.Println("nil!")
	

Creating a slice with make

用内置make函数创建slice,创建动态数组,make分配一个初始化为0的数组,返回对应数组的一个切片。

package main

import "fmt"

func main() 
	a := make([]int, 5)
	printSlice("a", a)

	b := make([]int, 0, 5)
	printSlice("b", b)

	c := b[:2]
	printSlice("c", c)

	d := c[2:5]
	printSlice("d", d)


func printSlice(s string, x []int) 
	fmt.Printf("%s len=%d cap=%d %v\\n",
		s, len(x), cap(x), x)

Slices of slices

package main

import (
	"fmt"
	"strings"
)

func main() 
	// Create a tic-tac-toe board.
	board := [][]string
		[]string"_", "_", "_",
		[]string"_", "_", "_",
		[]string"_", "_", "_",
	

	// The players take turns.
	board[0][0] = "X"
	board[2][2] = "O"
	board[1][2] = "X"
	board[1][0] = "O"
	board[0][2] = "X"

	for i := 0; i < len(board); i++ 
		fmt.Printf("%s\\n", strings.Join(board[i], " "))
	

Appending to a slice

func append(s []T, vs …T) []T
append的第一个参数s是一个T类型的切片,其余的是要追加到切片的T值。
append的结果值是一个包含原始切片的所有元素加上提供的值的切片。
如果s的支持数组太小,不能容纳所有给定的值,则会分配一个更大的数组。返回的切片将指向新分配的数组。

package main

import "fmt"

func main() 
	var s []int
	printSlice(s)

	// append works on nil slices.
	s = append(s, 0)
	printSlice(s)

	// The slice grows as needed.
	s = append(s, 1)
	printSlice(s)

	// We can add more than one element at a time.
	s = append(s, 2, 3, 4)
	printSlice(s)


func printSlice(s []int) 
	fmt.Printf("len=%d cap=%d %v\\n", len(s), cap(s), s)

Range

Range形式的for循环迭代一个slice或者map,有两个返回值,第一个是索引,第二个是索引值对应元素的拷贝。

package main

import "fmt"

var pow = []int1, 2, 4, 8, 16, 32, 64, 128

func main() 
	for i, v := range pow 
		fmt.Printf("2**%d = %d\\n", i, v)
	

通过"_"符号来跳过某个返回值:

for i, _ := range pow
for _, value := range pow
//如果只想要索引也可以写成如下形式
for i := range pow

Maps

key-value对

package main

import "fmt"

type Vertex struct 
	Lat, Long float64


var m map[string]Vertex

func main() 
	m = make(map[string]Vertex)
	m["Bell Labs"] = Vertex
		40.68433, -74.39967,
	
	fmt.Println(m["Bell Labs"])

package main

import "fmt"

type Vertex struct 
	Lat, Long float64


var m = map[string]Vertex
	"Bell Labs": Vertex
		40.68433, -74.39967,
	,
	"Google": Vertex
		37.42202, -122.08408,
	,


func main() 
	fmt.Println(m)

类型名可以省略

var m = map[string]Vertex
	"Bell Labs": 40.68433, -74.39967,
	"Google":    37.42202, -122.08408,

  • 插入或者更新元素
m[key] = elem
  • 取回元素
elem = m[key]
  • 删除元素
delete(m, key)
  • 测试元素
elem, ok = m[key]

Function values

函数可以作为数值传递。

Function closures

package main

import "fmt"

func adder() func(int) int 
	sum := 0
	return func(x int) int 
		sum += x
		return sum
	


func main() 
	pos, neg := adder(), adder()
	for i := 0; i < 10; i++ 
		fmt.Println(
			pos(i),
			neg(-2*i),
		)
	

以上是关于Go语言基础的主要内容,如果未能解决你的问题,请参考以下文章

Goland 基础语法

2.go命令源文件分析

Go语言介绍

go的匿名函数结尾圆括号的含义

Go语言基础

区块链基础语言——Go语言结构