parent
45f42568fc
commit
e1661b5dc4
195
docs/golang.md
195
docs/golang.md
@ -33,6 +33,8 @@ s1 = "Learn Go!"
|
||||
// 一次声明多个变量
|
||||
var b, c int = 1, 2
|
||||
var d = true
|
||||
// 匿名赋值
|
||||
_ , e = 10, 20
|
||||
```
|
||||
|
||||
简短声明
|
||||
@ -139,7 +141,6 @@ fmt.Println(!true) // false
|
||||
参见:[更多操作符](#运算符和标点符号)
|
||||
|
||||
### 数组 Arrays
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
|
||||
```go
|
||||
┌────┬────┬────┬────┬─────┬─────┐
|
||||
@ -183,7 +184,7 @@ fmt.Println("2d: ", twoDimension)
|
||||
```
|
||||
|
||||
### 指针(Pointers)
|
||||
|
||||
<!--rehype:wrap-class=col-span-2-->
|
||||
```go
|
||||
func main () {
|
||||
b := *getPointer()
|
||||
@ -194,9 +195,26 @@ func getPointer () (myPointer *int) {
|
||||
a := 234
|
||||
return &a
|
||||
}
|
||||
|
||||
a := new(int)
|
||||
*a = 234
|
||||
//申明指针的时候,如果没有指向某个变量,默认值为nil
|
||||
//不能直接进行操作,包括读写
|
||||
var p *int
|
||||
*p = 123 // panic nil pointer
|
||||
---
|
||||
//而用new返回的是有默认值的指针, 为数据类型的默认值
|
||||
func main(){
|
||||
//有一块内存存放了10,它的地址由系统自动分配,别名是a
|
||||
a := 10
|
||||
//内存存放的10变成了20
|
||||
a = 20
|
||||
var p *int
|
||||
p = &a //或者直接写 p := &a
|
||||
//上面的p是一个指针,通过 *p 的方式同样可以访问 变量a指向 的内存
|
||||
|
||||
/*当你动态申请内存的时候,指针的存在意义之一就被体现出来了*/
|
||||
ptr := new(int)
|
||||
//申请了一块内存空间,没有办法指定别名,new()返回内存地址,用指针接收
|
||||
//此时并没有变量能直接指向这块内存,所以只能通过内存地址来访问
|
||||
}
|
||||
```
|
||||
|
||||
参见:[指针(Pointers)](https://tour.golang.org/moretypes/1)
|
||||
@ -225,11 +243,27 @@ const s string = "constant"
|
||||
const Phi = 1.618
|
||||
const n = 500000000
|
||||
const d = 3e20 / n
|
||||
fmt.Println(d)
|
||||
|
||||
常量声明可以使用 iota常量生成器 初始化,它用于
|
||||
生成一组以相似规则初始化的常量,但是不用每行都
|
||||
写一遍初始化表达式。
|
||||
注意:
|
||||
1.在一个const声明语句中,在第一个声明的常量
|
||||
所在的行,iota被置为0,然后在每一个有常量声明的行加一。
|
||||
2.写在同一行的值是相同的
|
||||
|
||||
const (
|
||||
a = iota
|
||||
b
|
||||
c
|
||||
)
|
||||
// a = 0, b = 1, c = 2
|
||||
```
|
||||
|
||||
### 类型转换
|
||||
|
||||
Go语言中不允许隐式转换,所有类型转换必须显式声明(强制转换),而且转换只能发生在两种相互兼容的类型之间。
|
||||
|
||||
```go
|
||||
i := 90
|
||||
f := float64(i)
|
||||
@ -561,6 +595,8 @@ sum(1, 2) // => [1 2] 3
|
||||
sum(1, 2, 3) // => [1 2 3] 6
|
||||
nums := []int{1, 2, 3, 4}
|
||||
sum(nums...) // => [1 2 3 4] 10
|
||||
// 不定参在内存中是连续存储的
|
||||
// 不定参内部再传递的时候,参数也要是不定的
|
||||
```
|
||||
|
||||
### 初始化函数
|
||||
@ -597,20 +633,8 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
### 关闭 1
|
||||
|
||||
```go
|
||||
func scope() func() int{
|
||||
outer_var := 2
|
||||
foo := func() int {return outer_var}
|
||||
return foo
|
||||
}
|
||||
// Outpus: 2
|
||||
fmt.Println(scope()())
|
||||
```
|
||||
|
||||
### 关闭 2
|
||||
|
||||
### 闭包
|
||||
<!--rehype:wrap-class=col-span-2 row-span-2-->
|
||||
```go
|
||||
func outer() (func() int, int) {
|
||||
outer_var := 2
|
||||
@ -622,8 +646,25 @@ func outer() (func() int, int) {
|
||||
return inner, outer_var
|
||||
}
|
||||
inner, val := outer()
|
||||
fmt.Println(inner()) // => 200
|
||||
fmt.Println(val) // => 101
|
||||
fmt.Println(val)
|
||||
// => 101
|
||||
fmt.Println(inner())
|
||||
// => 200,这里涉及到golang中闭包和内存逃逸的概念,inner()实际上执行了两次,outer()中一次,fmt又一次,
|
||||
//但为什么是200呢,编译器不能确定outer_var在后续会不会使用,
|
||||
//所以outer_var不会随着outer()结束而释放它的栈(Stack)空间,
|
||||
//而会‘逃逸到’堆(Heap)上,那么第二次的inner()中outer_var就会是101。
|
||||
```
|
||||
|
||||
### 关闭 1
|
||||
|
||||
```go
|
||||
func scope() func() int{
|
||||
outer_var := 2
|
||||
foo := func() int {return outer_var}
|
||||
return foo
|
||||
}
|
||||
// Outpus: 2
|
||||
fmt.Println(scope()())
|
||||
```
|
||||
|
||||
Golang 包(Packages)
|
||||
@ -835,8 +876,21 @@ Golang 方法(Methods)
|
||||
<!--rehype:body-class=cols-2-->
|
||||
|
||||
### 接收器
|
||||
|
||||
<!--rehype:wrap-class=row-span-2-->
|
||||
```go
|
||||
//Go语言中的方法(Method)是一种作用于特定类型变量的函数。
|
||||
//这种特定类型变量叫做接收者(Receiver)。
|
||||
//接收者的概念就类似于其他语言中的 this 或者 self。
|
||||
//方法的定义格式如下:
|
||||
func (接收者变量 接收者类型) 方法名(参数列表) (返回参数) {
|
||||
函数体
|
||||
}
|
||||
// 其中,
|
||||
// 1.接收者变量:接收者中的参数变量名在命名时,官方建议使用接收者类型名
|
||||
//的第一个小写字母,而不是self、this之类的命名。例如,Person类型的接收者变量
|
||||
// 应该命名为 p,Connector类型的接收者变量应该命名为c等。
|
||||
// 2.接收者类型:接收者类型和参数类似,可以是指针类型和非指针类型。
|
||||
// 3.方法名、参数列表、返回参数:具体格式与函数定义相同。
|
||||
type Vertex struct {
|
||||
X, Y float64
|
||||
}
|
||||
@ -844,27 +898,82 @@ type Vertex struct {
|
||||
func (v Vertex) Abs() float64 {
|
||||
return math.Sqrt(v.X * v.X + v.Y * v.Y)
|
||||
}
|
||||
func (v Vertex) valuechange() float64 {
|
||||
v.X += 1
|
||||
return v.X
|
||||
}
|
||||
func (v *Vertex) pointerchange() float64 {
|
||||
v.X += 1
|
||||
return v.X
|
||||
}
|
||||
func main() {
|
||||
v := Vertex{1, 2}
|
||||
v.Abs()
|
||||
|
||||
v = Vertex{1, 2}
|
||||
fmt.Println(v.valuechange()) // 2
|
||||
fmt.Println(v) // {1 2}
|
||||
|
||||
v = Vertex{1, 2}
|
||||
fmt.Println(v.pointerchange())// 2
|
||||
fmt.Println(v) // {2 2}
|
||||
}
|
||||
//如果在方法里修改receiver的值要对caller生效,使用 pointer receiver。
|
||||
|
||||
v := Vertex{1, 2}
|
||||
v.Abs()
|
||||
```
|
||||
|
||||
参见:[Methods](https://tour.golang.org/methods/1)
|
||||
参见:[Methods](https://tour.golang.org/methods/1),[指针接收器](https://tour.golang.org/methods/4)
|
||||
|
||||
### Mutation
|
||||
### 方法表达式
|
||||
|
||||
方法表达式相当于提供一种语法将类型方法调用显式地转换为函数调用,接收者(receiver)必须显式地传递进去。
|
||||
|
||||
```go
|
||||
func (v *Vertex) Scale(f float64) {
|
||||
v.X = v.X * f
|
||||
v.Y = v.Y * f
|
||||
func (t T) Get(){
|
||||
return t.a
|
||||
}
|
||||
|
||||
v := Vertex{6, 12}
|
||||
v.Scale(0.5)
|
||||
// `v` 已更新
|
||||
func (t *T) Set(i int){
|
||||
t.a = i
|
||||
}
|
||||
//表达式`T.Get`和`(*T).Set`被称为方法表达式,
|
||||
//需要注意的是在方法表达式中编译器不会做自动转换。
|
||||
//值调用会自动转换,表达式调用则不会,例如:
|
||||
type Data struct{}
|
||||
func (Data) TestValue () {}
|
||||
func (*Data) TestPointer () {}
|
||||
//声明一个类型变量a
|
||||
var a Data= struct{}{}
|
||||
//表达式调用编译器不会进行自动转换
|
||||
Data.TestValue(a)
|
||||
//Data.TestValue(&a)
|
||||
(*Data).TestPointer (&a)
|
||||
//Data.TestPointer(&a) //type Data has no method TestPointer
|
||||
//值调用编译器会进行自动转换
|
||||
y : = (&a).TestValue //编译器帮助转换a.TestValue
|
||||
g : = a.TestPointer //会转换为(&a).TestPointer
|
||||
```
|
||||
|
||||
参见:[指针接收器](https://tour.golang.org/methods/4)
|
||||
#### 组合结构的方法集
|
||||
|
||||
内嵌字段的访问不需要使用全路径,只要保证命名是唯一的就可以,尽量避免同名。如果外层字段和内层字段有相同的方法,则使用简化模式访问外层方法会覆盖内层的方法。
|
||||
|
||||
```go
|
||||
x : = X{a: 1}
|
||||
y : = Y{
|
||||
X : x ,
|
||||
b : 2 ,
|
||||
}
|
||||
z : = z {
|
||||
Y : y ,
|
||||
c : 3 ,
|
||||
}//组合结构,内嵌字段
|
||||
```
|
||||
|
||||
组合结构的方法集有如下规则:
|
||||
|
||||
- 若类型 T 包含匿名字段 S ,则 T 的方法集包含S的方法集
|
||||
- 若类型 T 包含匿名字段 *S ,则 T 的方法集包含 S 和*S方法集
|
||||
- 不管类型 T 中嵌入的匿名字段是 S 还是 *S ,*T 方法集总是包含 S 和 *S 方法集
|
||||
|
||||
Golang 接口(Interfaces)
|
||||
--------
|
||||
@ -1006,11 +1115,11 @@ Go 命令
|
||||
另见
|
||||
--------
|
||||
|
||||
- [Devhints](https://devhints.io/go) _(devhints.io)_
|
||||
- [A tour of Go](https://tour.golang.org/welcome/1) _(tour.golang.org)_
|
||||
- [Golang wiki](https://github.com/golang/go/wiki/) _(github.com)_
|
||||
- [Effective Go](https://golang.org/doc/effective_go.html) _(golang.org)_
|
||||
- [Go by Example](https://gobyexample.com/) _(gobyexample.com)_
|
||||
- [Awesome Go](https://awesome-go.com/) _(awesome-go.com)_
|
||||
- [JustForFunc Youtube](https://www.youtube.com/channel/UC_BzFbxG2za3bp5NRRRXJSw) _(youtube.com)_
|
||||
- [Style Guide](https://github.com/golang/go/wiki/CodeReviewComments) _(github.com)_
|
||||
- [Devhints](https://devhints.io/go) *(devhints.io)*
|
||||
- [A tour of Go](https://tour.golang.org/welcome/1) *(tour.golang.org)*
|
||||
- [Golang wiki](https://github.com/golang/go/wiki/) *(github.com)*
|
||||
- [Effective Go](https://golang.org/doc/effective_go.html) *(golang.org)*
|
||||
- [Go by Example](https://gobyexample.com/) *(gobyexample.com)*
|
||||
- [Awesome Go](https://awesome-go.com/) *(awesome-go.com)*
|
||||
- [JustForFunc Youtube](https://www.youtube.com/channel/UC_BzFbxG2za3bp5NRRRXJSw) *(youtube.com)*
|
||||
- [Style Guide](https://github.com/golang/go/wiki/CodeReviewComments) *(github.com)*
|
||||
|
@ -113,7 +113,7 @@ $("selector1, selector2 ...selectorn")
|
||||
- [[name!="value"]](https://api.jquery.com/attribute-not-equal-selector/) _选择不具有指定属性或具有指定属性但不具有特定值的元素_<!--rehype:tooltips-->
|
||||
- [[name^="value"]](https://api.jquery.com/attribute-starts-with-selector/) _选择具有指定属性且值恰好以给定字符串开头的元素_<!--rehype:tooltips-->
|
||||
- [[name]](https://api.jquery.com/has-attribute-selector/) _选择具有指定属性和任意值的元素_<!--rehype:tooltips-->
|
||||
- [[name="value"][name2="value2"]](https://api.jquery.com/multiple-attribute-selector/) _匹配匹配所有指定属性过滤器的元素_<!--rehype:tooltips-->
|
||||
- [[name="value"]](https://api.jquery.com/multiple-attribute-selector/) _匹配匹配所有指定属性过滤器的元素_<!--rehype:tooltips-->
|
||||
<!--rehype:className=cols-2 style-none-->
|
||||
|
||||
### 子过滤器
|
||||
|
Loading…
x
Reference in New Issue
Block a user