golang
import-package
- 每个文件中必须指明自己所属的包
- 每个文件夹下只能有一个包
- import 语句
m "test-golang/foo"
绝对路径test-golang
是总的包名 在go.mod中定义/foo
是文件夹名 与包名无关m
是此文件夹中存在的包的别名 - 同一文件夹中(同一包)的不同文件中定义的符号 互相可见
golang的一个repo由一个或者多个module组成 一个module由一个或多个package组成 package是一个文件夹下一个或多个go源文件, 在相同的package下符号定义互相共享(可以在一个go文件中直接使用定义在另一个go文件但是相同package的符号) 一个repo 一般只含有一个module, module的定义文件是go.mod 其中声明了此module的 module path 首字母大写的符号导出
忽略unused xx 报警
go run -gcflags '-unused_pkgs -unused_vars' xx.go
dependency 依赖
go mod init xxx (you moudle path),所以一个正常的go的目录结构是这样的
you-project-dir
you-moude-dir
main.go
go.mod
go.mod 作用类似于package.json或者carg.yaml
l-function-args
func a(a1,a2 string) {
}
test test
package xxx
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
)
func TestXXXX(t *testing.T) {
assert.Equal(t, false, false)
}
文件名必须以_test 结尾
go test xxx
xxx是包名字 可以用正则 go test ./controller/*
go test如xx -run TEST_NAME
只测试特定的函数 只测试特定的函数
如何避免cache
go test --count=1
如何输出log
go test -v // --verbose go test 默认捕获输出.此外可以直接使用t.Logf(")
变量定义
package main
import "fmt"
func main() {
var a = "initial"
fmt.Println(a)
var b, c int = 1, 2
fmt.Println(b, c)
var d = true
fmt.Println(d)
var e int
fmt.Println(e)
f := "apple"
fmt.Println(f)
}
/*
go run variables.go
initial
1 2
true
0
apple
*/
control statement
package main
import "fmt"
func main() {
if 7%2 == 0 {
fmt.Println("7 is even")
} else {
fmt.Println("7 is odd")
}
if 8%4 == 0 {
fmt.Println("8 is divisible by 4")
}
if num := 9; num < 0 {
fmt.Println(num, "is negative")
} else if num < 10 {
fmt.Println(num, "has 1 digit")
} else {
fmt.Println(num, "has multiple digits")
}
}
function-define
func FUNC_NAME(ARG1 ARG1_TYPE,ARG2 ARG2_TYPE) RET_TYPE {
}
l-string
l-string-fmt
// https://golang.org/pkg/fmt/
// golang 采用的是常规的模板方式 %X 一般常用的有%v 打印结构体 %+v 结构体+fieldname %d 数字 %s 字符串
title := fmt.Sprintf("已采集%d个药草, 还需要%d个完成任务", progress, target)
容器
list
push
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)
}
interface
type INTERFACE_NAME interface {
FUNC_NAME(ARG) RET_TYPE
}
impl-interface
package main
import (
"fmt"
)
type Barkble interface {
bark() string
}
func cal(b Barkble) {
fmt.Printf(b.bark())
}
type Dog1 struct {
name string
}
func NewDog1() *Dog1 {
return &Dog1{name: "A"}
}
func (d *Dog1) bark() string {
return d.name
}
type Dog2 struct {
name string
}
func NewDog2() *Dog2 {
return &Dog2{name: "B"}
}
func (d *Dog2) bark() string {
return d.name
}
func main() {
cal(NewDog1())
cal(NewDog2())
}
l-struct
type STRUCT_NAME struct {
FIELD_NAME FIELD_TYPE,
FIELD_NAME FIELD_TYPE,
}
l-construct-struct
type Dog1 struct {
name string
}
func a() {
d := Dog1 {
name:"2"}
}
要注意的是如果没有逗号,则}不能另起新行,否则会报错
l-struct-anonymous
[]struct{ file, md5 string }
statement
select
loop
iterator
a := []string{"Foo", "Bar"}
for i, s := range a {
fmt.Println(i, s)
}
m := map[string]int{
"one": 1,
"two": 2,
"three": 3,
}
for k, v := range m {
fmt.Println(k, v)
}
common-container
list
array
quque
map
package main
import (
"fmt"
)
type A struct {
m map[uint64]uint64
}
func main() {
fmt.Println("Hello, playground")
a := new(A)
a.m = make(map[uint64]uint64)
a.m[1] = 2
fmt.Printf("%v", a)
}
package main
import (
"fmt"
)
func main() {
m := make(map[uint64]string)
m[1] = "1111"
m[3] = "1111"
fmt.Printf("%v\n", m)
fmt.Printf("%v\n", m[1])
fmt.Printf("%v\n", m[3])
}
l-array-access-syntax
l-array-range
package main
import (
"fmt"
)
func main() {
a := []int{1, 2, 3, 4}
b := a[0:1]
fmt.Printf("%v\n", a)
fmt.Printf("%v\n", b)
}
// [1 2 3 4]
// [1]
debug
更准确的说 是golang vscoe debug的配置
go test -c 可以直接编译某个测试文件为binary
以某个测试为入口 debug
-
配置vscode
{ "version": "0.2.0", "configurations": [ { "name": "Launch", "type": "go", "request": "launch", "mode": "test", "program": "${workspaceRoot}", "env": {}, "args": [ "-test.v", "-test.run", "TestPing2" ], "showLog": true } ] }
- 在测试文件中打上断点 点击debug
l-struct-
l-struct-mixin
define
type A struct {
a_name_1 string
a_name_2 string
}
type B struct {
A
b_name_1 string
}
// B 实际的field是 a_name_1 a_name_2 b_name_1
init
a := A{a_name_1: "a_1", a_name_2: "a_2"}
b1 := B{a,"b"}
b2 := B{A:a,b_name_1:"b"}
fmt.Printf("%+v\n", b1)
fmt.Printf("%+v\n", b2)
// 要注意的是不能混用 field:value,value [source](https://github.com/Unknwon/go-fundamental-programming/issues/8)
//[go-playground](https://play.golang.org/p/5BrRMGibttH)
l-profile
go test -cpuprofile cpu.prof -memprofile mem.prof go tool pprof mem.prof web
l-ffi
调用c
从c中读取
char * echo(char *name)
检测空指针
l-json
type response struct {
Page int `json:"page"`
Fruits []string `json:"fruits"`
}
l-type-from-json
res1D := &response{
Page: 1,
Fruits: []string{"apple", "peach", "pear"}
}
res1B, _ := json.Marshal(res1D)
fmt.Println(string(res1B))
## 避免html字符转义
https://blog.csdn.net/LinHenk/article/details/89636192
str := `{"page": 1, "fruits": ["apple", "peach"]}`
res := response{}
json.Unmarshal([]byte(str), &res)
fmt.Println(res)
fmt.Println(res.Fruits[0])
l-assert-json-stringl--eq
l-ffi
extern "C" int echo(char *OutBuffer, size_t &OutLen, const char *InBuffer, size_t InLen)
{
std::memcpy(OutBuffer, InBuffer, InLen);
}
l-call-ffi-dynmaic
package main
func main() {
}
l-call-ffi-static
windows
golang windows 静态链接很麻烦 放弃吧 用动态链接
linux
l-been-ffi
必须能够变成动态或者静态的c库