2020年1月

函数声明包含了函数名,形参列表,函数体和返回值。 func 函数名(形参列表) (返回值) {
函数体
}

返回值可以像形参一样命名,每一个返回的命名值会声明为一个局部变量,并根据变量类型初始化为相应的0值。

如果几个形参或返回值的函数类型相同,那么类型只需要写一次。如:

func f(i, j, k int, s, t string)

函数的类型称作函数签名,当两个函数拥有相同的形参列表和返回列表时,认为这两个函数的类型或签名都是相同的。

go语言没有默认参数值也不能指定实参名

go的实参是按值传递的

如果提供的实参包含引用类型(指针,slice,map,函数或者通道)那么函数使用这些变量将会简介的修改实参内容

go语言的垃圾回收机制将回收未使用的内存,但不能指望他会释放未使用的操作系统资源

一个多值调用可以作为单独的实参传递给拥有两个形参的函数中
比如:

func findLinksLog(url string) ([]string, error) {return nil, nil}

fmt.Println(findLinksLog(url));

一个函数如果有命名的返回值,可以省略return语句的操作数称为裸返回
func test() (a string, b int) {
a = "1"
b = 2
return //相当于 return a, b
}

函数变量不能比较所以不能用在map的键中

函数字面量在任何表达式内指定函数变量,函数字面量就像函数声明(就是函数变量)

拓展符
可以通过以下调用:

values := []int{1,2,3,4}
fmt.Println(sum(values...))

defer 以倒序进行

一个典型的宕机发生时goroutine中的所有延迟函数会执行,

可以利用recover函数对宕机进行恢复
比如:

func Parse(input string) (s *Syntax, err error){
    defer func(){
        if p := recover(); p!=nil {
        err = fmt.Errorf("internal error: %v", p)
    }
}

}

接口的nil有分 动态值nil 和 动态类型nil

比如:
var s interface{}
此时动态值和动态类型都为nil

如果是:
var s *bytes.Buffer
此时动态值为空,但是动态类型不是空 所以如下: 会为真
if s != nil {

}
当你实现了一个接口 然后调用此函数时,本质上go是调用了实现此接口的方法,然后给了这个接口对应的接收者地址。

1、struct转化为[]byte,转换方法如下:


import (
    "fmt"
    "unsafe"
)
type TestStructTobytes struct {
    data int64
}
type SliceMock struct {
    addr uintptr
    len  int
    cap  int
}

func main() {

    var testStruct = &TestStructTobytes{100}
    Len := unsafe.Sizeof(*testStruct)
    testBytes := &SliceMock{
        addr: uintptr(unsafe.Pointer(testStruct)),
        cap:  int(Len),
        len:  int(Len),
    }
    data := *(*[]byte)(unsafe.Pointer(testBytes))
    fmt.Println("[]byte is : ", data)
}

运行结果:

[]byte is : [100 0 0 0 0 0 0 0]
1
因为[]byte底层的数据结构为:
struct {
addr uintptr
len int
cap int
}
其中addr为数值的地址,len为当地数值的长度,cap为数值的容量。
转换的时候,需要定义一个和[]byte底层结构一致的struct(如例子中的SliceMock),然后把结构体的地址赋给addr,结构体的大小赋给len和cap。最后将其转换为[]byte类型。

2、将[]byte转换为struct,转换方法如下:


import (
    "fmt"
    "unsafe"
)
type TestStructTobytes struct {
    data int64
}
type SliceMock struct {
    addr uintptr
    len  int
    cap  int
}

func main() {

    var testStruct = &TestStructTobytes{100}
    Len := unsafe.Sizeof(*testStruct)
    testBytes := &SliceMock{
        addr: uintptr(unsafe.Pointer(testStruct)),
        cap:  int(Len),
        len:  int(Len),
    }
    data := *(*[]byte)(unsafe.Pointer(testBytes))
    fmt.Println("[]byte is : ", data)
    var ptestStruct *TestStructTobytes = *(**TestStructTobytes)(unsafe.Pointer(&data))
    fmt.Println("ptestStruct.data is : ", ptestStruct.data)
}

运行结果:

[]byte is : [100 0 0 0 0 0 0 0]
ptestStruct.data is : 100
1
2
从上面的例子中将[]byte转换为struct的代码片段为:

var ptestStruct TestStructTobytes = (**TestStructTobytes)(unsafe.Pointer(&data))
1
分析:
由于在golang中编译器不将[]byte视为指针,所以要使用其地址进行转换,由于[]byte底层存放的是指向数据的地址。用[]byte的地址就需要使用双层指针转换,然后再指向其内容,得出来的就是转换对应struct的指针了。

本软件尊重并保护所有使用服务用户的个人隐私权。为了给您提供更准确、更有个性化的服务,本软件会按照本隐私权政策的规定使用和披露您的个人信息。但本软件将以高度的勤勉、审慎义务对待这些信息。除本隐私权政策另有规定外,在未征得您事先许可的情况下,本软件不会将这些信息对外披露或向第三方提供。本软件会不时更新本隐私权政策。您在同意本软件服务使用协议之时,即视为您已经同意本隐私权政策全部内容。本隐私权政策属于本软件服务使用协议不可分割的一部分。

1.适用范围

a)在您使用本软件网络服务,本软件自动接收并记录的您的手机上的信息,包括但不限于您的健康数据、使用的语言、访问日期和时间、软硬件特征信息及您需求的网页记录等数据;

2.信息的使用

a)在获得您的数据之后,本软件会将其上传至服务器,以生成您的排行榜数据,以便您能够更好地使用服务。

3.信息披露

a)本软件不会将您的信息披露给不受信任的第三方。

b)根据法律的有关规定,或者行政或司法机构的要求,向第三方或者行政、司法机构披露;

c)如您出现违反中国有关法律、法规或者相关规则的情况,需要向第三方披露;

4.信息存储和交换

本软件收集的有关您的信息和资料将保存在本软件及(或)其关联公司的服务器上,这些信息和资料可能传送至您所在国家、地区或本软件收集信息和资料所在地的境外并在境外被访问、存储和展示。

5.信息安全

a)在使用本软件网络服务进行网上交易时,您不可避免的要向交易对方或潜在的交易对方披露自己的个人信息,如联络方式或者邮政地址。请您妥善保护自己的个人信息,仅在必要的情形下向他人提供。如您发现自己的个人信息泄密,请您立即联络本软件客服,以便本软件采取相应措施。

go会根据上下文来决定变量是分配到堆才是栈比如如下代码:

var global *int
func f(){
    var x int
    global = &x
}

此时x会分配到堆上。

如果两个类型具有相同的底层类型或两者都是指向相同底层类型变量的未命名指针类型,则二者是可以相互转换的。

init函数
一个包里可以定义多个init函数会顺序执行 init函数不能被调用

if 和 switch会创建有隐式词法块

if x := f(); x==0 {
    fmt.Println(x)
} else if y := g(x); x == y {
    fmt.Println(x, y)
} else {
    fmt.Println(x, y)
}

Go

  • 没有隐式数值类型强制类型转换
  • 没有构造或析构函数
  • 没有运算符重载
  • 没有形参默认值
  • 没有继承
  • 没有泛型
  • 没有异常
  • 没有宏
  • 没有函数注解
  • 没有线程局部存储

go run 包含了 编译、链接、运行

go build 编译

约定打开会执行package main 下的main方法

go在缺失导入或存在不需要的包的情况下会编译失败

for 是GO里唯一的循环语句

Go 不允许存在无用的临时变量

ioutil.Discard 无用输出流