21世纪的C语言, Go语言已经成为云计算、云存储时代最重要的基础编程语言
简洁编程哲学
特性
拥有自动垃圾回收、一个包系统、函数作为一等公民、词法作用域、系统调用接口、只读的UTF8字符串等
其他:
Go语言本身只有很少的特性 没有隐式的数值转换,没有构造函数和析构函数,没有运算符重载,没有默认参数,也没有继承,没有泛型,没有异常,没有宏,没有函数修饰,更没有线程局部存储
make it easy to write programs that get the most out of multicore and networked machines
贝尔实验室的UNIX和C语言两大发明奠定了整个现代IT行业最重要的软件基础
1970s Ken Thompson 和 Dennis M. Ritchie 合力开发 Unix 操作系统
Dennis M. Ritchie 为了解决UNIX系统的移植性问题而发明了C语言
Ken Thompson、Rob Pike、Robert Griesemer(设计了V8引擎和HotSpot虚拟机) 为了解决在21世纪多核和网络化环境下越来越复杂的编程问题而发明了Go语言
Go语言由来自Google公司的Robert Griesemer,Rob Pike和Ken Thompson三位大牛于2007年9月开始设计和实现,然后于2009年的11月对外正式发布
Go语言尤其适合编写网络服务相关基础设施,同时也适合开发一些工具软件和系统软件。 但是Go语言确实是一个通用的编程语言,它也可以用在图形图像驱动编程、移动应用程序开发 和机器学习等诸多领域。目前Go语言已经成为受欢迎的作为无类型的脚本语言的替代者: 因为Go编写的程序通常比脚本语言运行的更快也更安全,而且很少会发生意外的类型错误。
//@TODO github 网站学习
//@TODO PART II https://chai2010.cn/advanced-go-programming-book/
命令行
# 安装包
go get <path>
# 安装且更新为最新的包
go get -u <path>
# 升级全部依赖
go get -u all
# go fmt
# go 脚本格式化; 全目录,like IDE
go fmt ./...
# 列表当前项目包或模块
go list -m -json all
nm 输出在给定的可执行文件、对象文件或存档中涉及的符号。
# 打印中 yangsu.exe 的符号
#
# 如果使用 <-ldflags "-s -w"> 清除符号后,无法获取符号
go tool nm ./yangsu.exe
Go 语言族
workshop GOPATH 用于可指明其目录
工作区
中包
包
// path = ../name
package name
单个包中包名应该一致。
go 拥有一个轻量级的测试框架,通过
go test
命令进行测试
测试文件名 {name}_test.go
测试方法入口 Test{name}
func TestName (t *testing.T)
// t.Error/t.Fail 意识着测试失败
执行测试命令
# 指定文件夹
go test ./str/
# 指定文件
go test -v ./str/calc_test.go ./str/calc.go
# 指定文件函数
go test -v ./str/ '-test.run' TestFloatSimple
# 指定包以及测试函数
go test -v ./ysu/tools '-test.run' '^\QTestNewXRsa\E$'
Benchmark golang 自带的基准测试:
func BenchmarkStructToMapLStyle(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
StructToMapLStyle(tom)
}
}
// goos: windows
// goarch: amd64
// pkg: gitee.com/conero/uymas/util
// cpu: xxx(R) Core(TM) i5-10200H CPU @ 2.40GHz
// BenchmarkStructToMapLStyle
// BenchmarkStructToMapLStyle-8 90331 12899 ns/op
// 标识循环:90331 次, 每次循环花费的时间: 12899 ns.
$> go fetch {url} 获取并安装远程包
go 语言中调用 c/c++
golang的cgo是调用gcc编译c代码的,gcc工具链在linux上很方便,但windows上是没有的。而windows上一般用的vc,golang是不支持的。
可用 MinGW
环境安装/window下 MinGW
window 需要环境 64位 gcc
编译器,如: mingw-64 网站 / 下载地址;32 位下 cgo 不可用。
文件下载历史:https://sourceforge.net/projects/mingw-w64/files/mingw-w64/
go 编译为 dll 文件
# 编译单文件
go build -buildmode=c-shared -o exportgo.dll exportgo.go
# 编译目录
go build -buildmode=c-shared -o shared.dll .
主要特性
值类型, 应用类型
类型
字符串, "" 以及 `` 表示
func main(){
var str1 = "字符串"
str2 := `多行字符串`
fmt.Println(str1, str2)
}
域源代码为 utf-8 编码格式
大小写敏感
注释, // 单行, /多行/
func init(){
// 单行注释
t1, n1 := `ffff`, 5
/*
多行注释
*/
fmt.Println(t1, n1)
}
tokens : 标识符,关键字,运算符和标点符号以及文字
标识符中的第一个字符必须是字母。以字母开头
关键字
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
运算符和标点符号
+ & += &= && == != ( )
- | -= |= || < <= [ ]
* ^ *= ^= <- > >= { }
/ << /= <<= ++ = := , ;
% >> %= >>= -- ! ... . :
&^ &^=
整形
支持十进制、八进制、十六进制
float 浮点数
n10, n8, n16 := 0, o5, 0x100
f1, f2 := 072.47, 3.45e5
// 1e-3 = 0.001
// 1e3 = 1000
// utype = 2^n - 1
uint8 the set of all unsigned 8-bit integers (0 to 255), 2百
uint16 the set of all unsigned 16-bit integers (0 to 65535), 6万
uint32 the set of all unsigned 32-bit integers (0 to 4294967295) 42亿
uint64 the set of all unsigned 64-bit integers (0 to 18446744073709551615)
int8 the set of all signed 8-bit integers (-128 to 127)
int16 the set of all signed 16-bit integers (-32768 to 32767)
int32 the set of all signed 32-bit integers (-2147483648 to 2147483647)
int64 the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807)
float32 the set of all IEEE-754 32-bit floating-point numbers
float64 the set of all IEEE-754 64-bit floating-point numbers
complex64 the set of all complex numbers with float32 real and imaginary parts
complex128 the set of all complex numbers with float64 real and imaginary parts
byte alias for uint8
rune alias for int32
uint either 32 or 64 bits
int same size as uint
uintptr an unsigned integer large enough to store the uninterpreted bits of a pointer value
string_lit = raw_string_lit | interpreted_string_lit
// 原始字符串
raw_string_lit = "`" { unicode_char | newline } "`"
// 解析字符串
interpreted_string_lit = `"` { unicode_value | byte_value } `"`
n := len(raw_string_lit) // 0 ... len(s) -1
转义字符
\x0c 清屏并输出
类型
Rune, integer, floating-point, and complex constants are collectively called numeric constants.
结构化的变量: array, slice, map
复合类型 Composite types
array, struct, pointer, function, interface, slice, map, and channel
基础类型/ underlying type
boolean, numeric, or string
go 语言采用 组合继承 ;接口实现的方法,一个
struct
实现interface
所有方法则实现了接口
package main
import "fmt"
type A interface {
Name() string
Cal(params ...int) int
}
type A1 struct {
}
func (a1 *A1) Name() string {
return "Add"
}
func (a1 *A1) Cal(params ...int) int {
all := 0
for _, n := range params {
all += n
}
return all
}
type A2 struct {
}
func (a2 *A2) Name() string {
return "Reduce"
}
func (a2 *A2) Cal(params ...int) int {
all := 0
for _, n := range params {
all -= n
}
return all
}
func GetA(vtype string) A {
var a A = nil
switch vtype {
case "A1":
//a = A1{}
// ERROR: cannot use A1 literal (type A1) as type A in assignment:
a = new(A1)
case "A2":
a = new(A2)
}
return a
}
func main() {
param := []int{100, 10, 1, 0}
var a1, a2 A
a1 = GetA("A1")
a2 = GetA("A2")
fmt.Println(a1.Name(), a1.Cal(param...))
fmt.Println(a2.Name(), a2.Cal(param...))
}
go 组合与继承的区别:
如果一个struct嵌套了另一个有名结构体,那么这个模式就叫组合。
如果一个struct嵌套了另一个匿名结构体(只有类型没有名字),那么这个结构可以直接访问匿名结构体的方法,从而实现了继承。
如果一个struct嵌套了多个匿名结构体,那么这个结构可以直接访问多个匿名结构体的方法,从而实现了多重继承。
通过 $ go env
可以查看go安装的配置信息
Goroot: go的安装路径,官方包路径根据这个设置自动匹配。如同golang的安装一致。
Gopath: 工作路径,如果设置错误可能是系统运行有问题。尤其是在这种情况下安装的第三方包,在引用是也会出错。我的经验是这种情况下,应该卸载掉当前的语言环境,重新安装。
绝对路径/相对路径 加载文件/包
面展示了一些import常用的几种方式,但是还有一些特殊的import,让很多新手很费解,下面我们来一一讲解一下到底是怎么一回事
点操作
我们有时候会看到如下的方式导入包
go import( . "fmt" )
这个点操作的含义就是这个包导入之后在你调用这个包的函数时,你可以省略前缀的包名,也就是前面你调用的fmt.Println("helloworld")
可以省略的写成Println("helloworld")
别名操作 别名操作顾名思义我们可以把包命名成另一个我们用起来容易记忆的名字
import(
f "fmt"
)
别名操作的话调用包函数时前缀变成了我们的前缀,即 f.Println("helloworld")
_ 操作 这个操作经常是让很多人费解的一个操作符,请看下面这个import
import (
"database/sql"
_ "github.com/ziutek/mymysql/godrv"
)
_
操作其实是引入该包,而不直接使用包里面的函数,而是调用了该包里面的init
函数
注意: 同一个目录下不能定义不同的package 应该分为两个不同的目录才可以。 go,模块中要导出的函数,必须首字母大写。也即是 大写开头方法为共有方法,否则包内私有方法
CSP 线程并发模型
分为两种: 无缓存通道
、带缓存通道
。单数据传递使用无缓存通道可行,大量数据需要带缓存的通道。
// 无缓存的数据通道
ch := make(chan int)
// 带缓存的数据通道
ch2:= make(chan int, 1024)
golang 注释文档格式
//
后面要加空格, 例如: // xxx
package, const, type, func
等关键字
上面并且紧邻关键字的注释才会被展示// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// 注: 上面注释不会显示为文档;单独的 “//” 可用换行
// Package path implements utility routines for manipulating slash-separated
// paths.
//
// The path package should only be used for paths separated by forward
// slashes, such as the paths in URLs. This package does not deal with
// Windows paths with drive letters or backslashes; to manipulate
// operating system paths, use the path/filepath package.
package path
Package
的注释如果行数过多可以考虑用 doc.go
文档代替
如果当前包目录下包含多个Package注释的go文件(包括doc.go), 那么按照文件名的字母数序优先显示
Package
的注释会出现在godoc的包列表中, 但只能展示大约523字节的长度
在无效注释中以BUG(who)
开头的注释, 将被识别为已知bug, 显示在bugs
区域
// BUG(who): 我是bug说明
// Package banana ...
package banana
如果bug注释
和关键字注释
中间无换行, 那么混合的注释
将被显示在bugs
和godoc列表
两个区域内
// BUG(who): 我是bug注释
// Package banana ...也是pkg注释
package banana
URL将被转化为HTML链接
Example
example
开头, _
连接, test
结尾, 如:example_xxx_test.go
当前包名
+ _test
, 如: strings_test
func Example[FuncName][_tag]()
// Output:
注释, 说明函数返回的值命令行
# 开启一个godoc小型server, -play可以使用playground运行Example代码
godoc -http=:6060 -play
// Deprecated: 遗弃代码,IDE 高亮显示
go 编译器命令行参考
查看帮助
go help
go get = git clone + go install
# 代码编译
go build 加上可以编译的go源文件可以得到一个可执行文件。
# 批量[cmd]下所有二级制程序编译
# 注意:cmd 目录有效,其他目录经测试无法通过
go build -o ./bin ./cmd/...
# 使用 ldflags 简化过编译文件大小
# 优化文件大小
# -s 忽略调试信息
# -w 忽略DWARF表符号
go build -o ./bin -ldflags "-s -w" ./cmd/...
# go 代码生成,当前下的所有代码
go generate ./...
# 本地项目安装
go install 在编译源代码之后还安装到指定的目录
# 依赖下载,在mod开启的情况下,其实下载到本地项目
go get 从指定源上面下载或者更新指定的代码和依赖,并对他们进行编译和安装
#
#
# 项目模块
go mod 项目模块系统
go mod init 项目初始化
# 项目不在 【GOPATH】中时,需要指定模块名称,如
go mod init [module]
go mod vendor 模块自动拉取,并生产vendor目录
go 自定义tag编译
// +build embed_mode
// 自定义编译模式
脚本写法2
//go:build embed
// 自定义编译模式
# 使用自定义模式进行编译即可
go build -tags embed_mode
# 支持多个tags 如t1/t2/t3
go build -tags "t1 t2 t3"
# 不使用 tags
go build
go 1.11 新增 对 go module 的支持,提供 vendor 库支持;而 gopath 几何与 go 一起诞生,后者必须在 gopath 进行项目开发。
实际测试 IntellJ + go plugin 时间: 2019年10月25日 星期五, 无法友好的提示 vendor 目录下的依赖,虽然可运行带不够友好。
go module 使用 replace 指令
module conero.cn/firefly/secret
go 1.21.3
replace conero.cn/firefly/ffutil => ../ffutil
require (
conero.cn/firefly/ffutil v0.0.0 // 可以是任意占位符版本号
gitee.com/conero/uymas v1.4.0-alpha.1.0.20240116060107-6d9af8acb109
)
使用 go mod vendor
可更新,replace下的最新代码。
编译常量,也称编译标签。其在文件的首行:
// +build
// 示例
// +build linux darwin
// +build amd64
// +build linux,386 darwin,!cgo
// +build linux,cgo darwin,cgo
// +build !linux,!darwin !cgo
// 操心系统来源常量: runtime.GOOS
// 操心系统架构来源常量: runtime.GOARCH
条件编译也可在文件命名是指定,指定规则:
*_GOOS
*_GOARCH
*_GOOS_GOARCH
# 如:
# source_windows_amd64.go
go/src/builtin/builtin.go 内建函数文档包,可直接使用而不用引入包
go调用C/C++,或dll文件
无参数、返回值
main 只能应用于package main
init 能够应用于所有的package 可选
C/C++中接收命令行参数是通过~main函数传入,而go可以使用 os ,flag 库。 os.Args 命令行
地址
type T1 struct{
}
t1 := &T1{} // T1 的地址
t2 := *t1 // t1 的值
格式化
范本: 2006-01-02 15:04:05
如: 获取当前的时间
time.Now().Format("2006-01-02 15:04:05")
# golangci-lint
golangci-lint run
# 运行所有
golangci-lint run ./...
# 指定目录
golangci-lint run dir1 dir2/...
golangci-lint run file1.go
跨平台的 GUI 库,GitHub代码库。
window GUI APP 默认含 cmd 窗口,可使用参数选项来消除
go build -ldflags -H=windowsgui <filename>
要使用 Golang 开发 WebSocket,选择基本就在 x/net/websocket 和 gorilla/websocket 之间。《Go Web 编程》一书中的例子使用了 x/net/websocket
作为开发包,而且貌似它也更加官方且正式。而实际根据我在网上查询得到的反馈看来,并非如此。x/net/websocket
貌似 Bug 较多,且较为不稳定,问题解决也并不及时。相比之下,gorilla/websocket
则更加优秀。
参考:golang-standards/project-layout
主要目录结构
386 编译的程序为: 32位。
# 设置环境变量
# linux, darwin, windows, netbsd
$env:GOOS="linux"
# 系统架构
# amd64, 386, arm, ppc64
$env:GOARCH = "amd64"
# 运行,即使对应操作系统的脚本
go build
操作系统 GOOS | 支持架构 GOARCH | |
---|---|---|
windows | 386, amd64 | |
linux | 386,amd64,arm,arm64,ppc64,ppc64le,mips,mipsle,mips64,mips64le,s390x | |
darwin | amd64,arm64 | |
android | 386,amd64,arm,arm64 | |
aix | ppc64 | |
dragonfly | amd64 | |
freebsd | 386,amd64,arm | |
illumos | amd64 | |
js | wasm | |
netbsd | 386,amd64,arm | |
openbsd | 386,amd64,arm,arm64 | |
plan9 | 386,amd64,arm | |
solaris | amd64 |
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。