抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

Go 语言是谷歌 2009 发布的第二款开源编程语言。

创建项目

新建文件夹 helloworld,新建main.go

package main
import "fmt"

func main() {
	fmt.Println("Hello world!")
}

然后打开Terminal

# 初始化模块
go mod init helloworld 
# 编译并运行
go build && ./helloworld

# output:
Hello world!

go mod是 Go 语言管理模块依赖的工具,有点类似 npm,yarn

go mod最佳实践 · go语言应急手册 · 看云 (kancloud.cn)

变量

Go 语言中的变量和其他语言大同小异:数据类型基本一致,只是关于全局和局部作用域对变量初始化的限制有所不同。

数据类型

  • 布尔型(bool): 值只可以是常量 true 或者 false
  • 数字类型: 整型 int 和浮点型 float,支持复数(业务代码用不到),其中位的运算采用补码。
  • 字符串类型(string): 使用UTF-8编码标识Unicode文本。
  • 其他:指针、数组、结构体(struct)、联合体 (union不常用)、函数、切片、接口(interface)、MapChannel

声明变量的方式

你可以直接通过 var 声明、批量声明、语法糖简写

// 各种定义变量方式
func sampleDefineVariable() {
	// var identifier type
	var name string
	name = "s"

	//根据赋值自动判断类型
	var p = name

	//直接声明并赋值(必须是初次声明才有冒号)
	p2 := "as"
	//多变量声明,不赋值自动赋值为0,比如d e f
	var a, b, c = 1, 2, 3
	var d, e, f int
	h, i, j := 1, 2, 3

	//类型不同的多个变量,难看的要死
	var (
		k int
		l string
	)

	var m, n, o = "a", 1, true

	fmt.Println(name + p + p2 + l + m)
	fmt.Println(a + b + c + d + e + f + h + i + j + k + n)
	fmt.Println(o)
}

注意:已经声明并初始化的变量必须使用,不然编译不通过

全局和局部变量

image-20220227144730282

结论:

全局变量可以不初始化不使用

局部变量必须初始化并使用

不知道为什么会有这种规定

常量

Go 的常量也是和其他语言差不多,多了个亮点:枚举

常量写法:

const identifier [type] = value

常量必须赋初始值!!

批量创建常量并使用iota递增

func sampleDefineVariable() {
	const (
		F = iota // 0
		G = iota // 1
		H = iota // 2
	)
	fmt.Println(F, G, H) // 0 1 2
}

iota默认从 0 开始递增,初次看到这个感觉没什么用,来点最佳实践!

const (
		_  = iota
		KB = 1 << (10 * iota)
		MB = 1 << (10 * iota)
		GB = 1 << (10 * iota)
		TB = 1 << (10 * iota)
		PB = 1 << (10 * iota)
	)

条件分支

package main

import (
	"fmt"
	"math"
)

func pow(x, n, lim float64) float64 {
	if v := math.Pow(x, n); v < lim {
		return v
	} else {
		fmt.Printf("%g >= %g\n", v, lim)
	}
	// 这里开始就不能使用 v 了
	return lim
}

func main() {
	fmt.Println(
		pow(3, 2, 10),
		pow(3, 3, 20),
	)
}

Go 语言中的if第一个位置类似 for循环的第一个参数,可以执行表达式,声明的变量其作用域仅仅存在代码块中。

循环

我不经常用switch,原因应该都知道吧

为什么很多程序员不用switch,而是大量的if……else if?-头条问答 (toutiao.com)

我也不经常用while,golang 中没有 while 而是用 for代替

Go 只有一种循环结构:for 循环。

基本的 for 循环由三部分组成,它们用分号隔开:

func main() {
	sum := 0
	for i := 0; i < 10; i++ {
		sum += i
	}
	fmt.Println(sum) // 45
}
  • 初始化语句:在第一次迭代前执行
  • 条件表达式:在每次迭代前求值
  • 后置语句:在每次迭代的结尾执行

初始化语句通常为一句短变量声明,该变量声明仅在 for 语句的作用域中可见。

一旦条件表达式的布尔值为 false,循环迭代就会终止。

注意:和 C、Java、JavaScript 之类的语言不同,Go 的 for 语句后面的三个构成部分外没有小括号, 大括号 { } 则是必须的。

和其他语言一样,for 三个位置都是可选的,哈哈哈

image-20220227152046624

推迟语句

defer会将后面表达式推迟到函数 return之后执行。

推迟的函数调用会被压入一个栈中。当外层函数返回时,被推迟的函数会按照后进先出的顺序调用。

package main

import "fmt"

func main() {
	defer fmt.Println("world")

	fmt.Println("hello")
}
/*
hello
world
*/

这个有什么用?网络 I/O、文件 I/O 操作之后主动关闭,避免死锁

Go Defer 高级实践 - SegmentFault 思否

结束

第一次接触到了 Go 语言的 defer ,感觉很像 react 中的 useEffectreturn,不得不佩服谷歌开发者,能想出这么优雅的处理方式。

参考:

go语言应急手册 · 看云 (kancloud.cn)

Go 语言之旅 (go-zh.org)

评论