第二章


go结构体函数

这个有点类似于显示对象传递func (a 结构体名) 方法名(参数列表) (返回值列表) {函数体}

如果我们想访问这个结构体成员的内容时,没有this指针这个概念的,需要显式的调用

匿名函数

如果我们要初始化匿名函数,可以使用下面这样的方法

// 这个是带返回值的 
f:=func()string{
      return "hello world"
 }
 a:=f()
// 当然我们可以直接调用
func(a int)string{
      return "hello world"
 }(4)

goto语句

go是支持goto语句的,不过一般不推荐使用

package main

import "fmt"

func main() {
   /* 定义局部变量 */
   var a int = 10

   /* 循环 */
   LOOP: for a < 20 {
      if a == 15 {
         /* 跳过迭代 */
         a = a + 1
         goto LOOP
      }
      fmt.Printf("a的值为 : %d\n", a)
      a++  
   }  
}

go返回值说明

go要求返回参数要么都有变量名要么都没有,必须统一。

import

go的import的最后面一个元素是包名

  1. import后面跟的是包的路径,而不是包名;
  2. 同一个目录下可以有多个.go文件,但是只能有一个包;
  3. 使用第三方库时,先将源码编译成.a文件放到临时目录下,然后去链接这个.a文件,而不是go install安装的那个.a文件;
  4. 使用标准库时,直接链接.a文件,即使修改了源码,也不会从新编译源码;
  5. 不管使用的是标准库还是第三方库,源码都是必须存在的,即使使用的是.a文件。

go数据类型

go的关键字

go关键字:

var和const :变量和常量的声明

var varName type 或者 varName : = value
package and import: 导入
func: 用于定义函数和方法
return :用于从函数返回
defer someCode :在函数退出之前执行
go : 用于并行
select 用于选择不同类型的通讯
interface 用于定义接口
struct 用于定义抽象数据类型
break、case、continue、for、fallthrough、else、if、switch、goto、default 流程控制
chan用于channel通讯
type用于声明自定义类型
map用于声明map类型数据
range用于读取slice、map、channel数据

有缓冲的channel和无缓冲的channel比较

无缓冲的channel是同步的,而有缓冲的channel是非同步的

比如c1:=make(chan int) 无缓冲

c2:=make(chan int,1) 有缓冲

c1<-1

无缓冲的 不仅仅是 向 c1 通道放 1 而是 一直要有别的携程 <-c1 接手了 这个参数,那么c1<-1才会继续下去,要不然就一直阻塞着

而 c2<-1 则不会阻塞,因为缓冲大小是1 只有当 放第二个值的时候 第一个还没被人拿走,这时候才会阻塞。

打个比喻

无缓冲的 就是一个送信人去你家门口送信 ,你不在家 他不走,你一定要接下信,他才会走。

无缓冲保证信能到你手上

有缓冲的 就是一个送信人去你家仍到你家的信箱 转身就走 ,除非你的信箱满了 他必须等信箱空下来。

有缓冲的 保证 信能进你家的邮箱

delete函数

delete 关键字用于删除哈希表 map 中的元素, 参数为 map 和其对应的 key

for循环

1.for循环支持continue和break来控制循环,但是它提供了一个更高级的break,可以选择中断哪一个循环

2.go里面没有while和都 while循环,循环全部用的是for循环

go的i++

go语言中的++、–操作符都是后置操作符,必须跟在操作数后面,并且它们没有返回值,所以它们不能用于表达式。

go语言的main函数

  1. main函数不能带参数
  2. main函数不能定义返回值
  3. main函数所在的包必须为main包
  4. main函数中可以使用flag包来获取和解析命令行参数

nil类型

Go语言中的引用类型只有五个:

切片 映射 函数 方法 通道

nil只能赋值给上面五种通道类型的变量以及指针变量。

go vendor

  1. 基本思路是将引用的外部包的源代码放在当前工程的vendor目录下面
  2. 编译go代码会优先从vendor目录先寻找依赖包
  3. 有了vendor目录后,打包当前的工程代码到其他机器的$GOPATH/src下都可以通过编译

接口

只要两个接口拥有相同的方法列表(次序不同不要紧),那么它们就是等价的,可以相互赋值。 Go语言接口是否可以赋值,是在编译期就确定的。接口的查询是在运行期确定。

A是B的子集,意味着A的方法B中都有,那么A是B的基类,所以A=B是可行的

init函数

  1. init函数可以在任何包中有0个或1个或多个;
  2. 首先初始化导入包的变量和常量,然后执行init函数,最后初始化本包的变量和常量,然后是init函数,最最后是main函数;
  3. main函数只能在main包中有且只有一个,面包中也可以有0或1或多个init函数;
  4. init函数和main函数都不能被显示调用;

字符串

GO语言中字符串是不可变的,所以不能对字符串中某个字符单独赋值。

map

因为map本身是无序的,for range根据循环对象本身的序列顺序进行遍历,所以 map在 for range 中是无序遍历的,每次遍历的顺序可能都不一样。

go … 操作符

这个一般用于函数拥有多个参数的情况下

下面这种方式调用是没有问题的

add([]int{1, 3, 7}...)

当然这个也可以不用


文章作者: 小游
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 小游 !
  目录