前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >go 笔记

go 笔记

作者头像
槽痞
发布2020-06-23 15:16:57
4000
发布2020-06-23 15:16:57
举报
  • 包名: 按照惯例, 包应当以小写的单个单词来命名,且不应使用下划线或驼峰记法。
  • 接口名:按照约定,只包含一个方法的接口应当以该方法的名称加上-er后缀来命名,如 Reader、Writer、 Formatter、CloseNotifier 等。
  • 在满足下列条件时,已被声明的变量 v 可出现在:= 声明中:
代码语言:javascript
复制
本次声明与已声明的 v 处于同一作用域中(若 v 已在外层作用域中声明过,则此次声明会创建一个新的变量§),
在初始化中与其类型相应的值才能赋予 v,且在此次声明中至少另有一个变量是新声明的。
  • 值得一提的是,即便Go中的函数形参和返回值在词法上处于大括号之外, 但它们的作用域和该函数体仍然相同。
  • 小写字母开头的函数,类型,变量,只在本包内可见,大写字母开头的函数,类型,变量才能被其他包使用
  • 切片动态增减元素,使用append方法,如果增加元素的是另外的切片,则需要使用append(mySlice,mySlice2...)三点
  • 在函数和方法中,如果参数是slice,那么本身传入的时候就是以地址的形式传入的
  • 数组切片支持copy()方法,用于将内容从一个切片复制到另外的一个切片
  • 浮点数的比较不能直接用==,可以自定义一个精度,再用两者的差的绝对值去和精度比较,如果小于精度值,则认为两者相等,和C语言类似。
代码语言:javascript
复制
import "math"
/**
判断两值是否相等
**/
func IsEqual(f1,f2,p float64) bool{
   return math.Abs(f1-f2) < p
}
  • 不能把函数的return语句放在 包含if...else分支中,否则会编译失败
  • switch是不需要别的语言中的default关键字的。 如果不设定swich后面的表达式,则相当于if...else...的作用;如果一个case紧跟下一个case,则需要在当前case中加上fallthrough关键字
  • go语言的for循环不支持以逗号为间隔的多个赋值语句,必须使用平行赋值的形式来初始化多个变量;break语句可以选择跳出哪一层。goto关键字可以跳到本函数内的某个标签
代码语言:javascript
复制
a := []int{1, 2, 3, 4, 5,6,7}
    JLOOP:
    for i,j := 0,len(a)-1;i < j; i, j =  i + 1, j-1 {
        a[i], a[j] = a[j], a[i]
        break JLOOP
    }
  • 一个加法函数
代码语言:javascript
复制
func Add(a,b int) (ret int,err error){
    if a < 0 || b < 0 {
        err = errors.New("Should be non-negative number")
    }
    return a+b, nil
}
  • 函数的不定参数,语法糖 ...type,再用for...range...进行迭代获取.如果希望传入任意类型的可以指定类型为interface{},如:
代码语言:javascript
复制
func printf(fomrt string, args ...interface{}){
}
  • 可以用 switch arg.(type)来进行变量的类型判断
  • panic()方法,接收任意的数据类型,调用时正常的函数执行流程将立即终止。
  • recover()函数用于终止错误流程处理,一般情况下,recover()应该在一个使用了defer 关键字的函数中执行以有效截取错误处理流程。
代码语言:javascript
复制
defer func(){
    if r := recover(); r != nil{
        log.Printf("Runtime error caught:%v",r)
    }

结构体:定义的一组字段的集合 结构体初始化,new(Student) == &Student{}是等价的。 接口:定义的一组方法的集合

  • go语言在面向对象的时,只有当需要修改对象的时候,才必须使用指针。它不是go语言的约束,而是一种自然约束。
代码语言:javascript
复制
func (a *Integer ) Add (b Integer) {
    retrun *a + b
}

go 结构体中的字段还有一个 在变量类型后还有一个tag,作为可选项,要获取tag内容,需要利用反射包来实现的。


  • 值类型:变量直接直接存储值,内存通常在栈上分配,基本数据类型int,float,bool,string,以及数组和struct
  • 引用传递:变量存储的是一个地址,这个地址存储最终的值,内存通常在堆上分配,通过GC回收,指针,slice,map,chan等都是引用类型

  • defer用途: 1.当函数返回时,执行defer语句,因此,可以用来做资源清理(比如数据库连接释放,锁释放)。 2.多个defer语句,按先进后出的方式执行。 3.defer语句中的变量,在defer 声明时就决定了。

内置函数 new:用来分配内存,主要用来分配值类型,比如int,struct,返回的是指针。 make:用来分配内存,主要用来分配引用类型,比如chan,map,slice,出现这种用差异的原因在于,这三种类型本质上为引用数据类型,它们在使用前必须初始化。 panicrecovery用来处理错误。


...有两个作用,一是作可变参数,另外可以把一个把一个slice展开


递归的设计原则: 1.一个大的问题能分解成相似的小的问题 2.定义好出口条件


闭包:一个函数和与其相关的引用环境组合而成的实体。 函数的返回值是一个函数


sort 包可以进行排序,使用sort.SearchInts()方法时需要传的参,slice必须是有序的


var mapkeTyPE 也可以用make初始化

a["hello"] = "world" //插入和更新 val,ok := a["hello"] //查找 delete(a,"hello") //删除 for k,v := range a{

代码语言:javascript
复制
fmt.Println(k,v)

}


锁机制: 1.互斥锁 Mutex

2.读写锁 Rwmutex

struct的内存布局,struct中所有字段在内存是连续的

*双链表定义:如果有两个指针分别这指向前一个节点和后一个节点,我们就叫双链表


链表:尾部插入法,头部插入法 type Student struct{ Name string Next *Student }


二叉树:如果每个节点有两个指针分别用来指向左子树和右子树,我们把这样的结构叫做二叉树 type Student struct{ Name string left *Studnent right *Student }

遍历时有深度优先和广度优先的方法 深度优先,可以用递归

广度优先,可以用队列


  • golang中没有构造函数,一般用工厂模式来解决问题
  • 再次强调,make用来创建map,slice,channel
  • new用来创建值类型,返回的是一个指针

在结构体中,结构体中的匿名字段可以实现其他语言中的所谓“继承”的效果,即一个结构体嵌套了另外一个匿名结构体。

结构体是用户单独定义的类型,不能和其他类型进行强制转换。

  • interface类型可以定义一组方法,但是这些不需要任何实现,并且interface不能包含任何变量。
  • golang中的接口,不需要显式的实现。只需要一个变量,含有接口类型中的所有方法,那么这个变量就实现这个接口。因此,golang中没有implement类似的关键字。
  • 如果一个变量含有了多个interface类型的方法,那么这个变量就实现了多个接口。
  • 一个接口可以嵌套在另外的接口。
  • 多态:一种事物的多种形态,都可以按照统一的接口进行操作
  • 类型断言:由于接口是一般类型,不知道具体类型,如果要转成具体类型,可以采用以下方法:
代码语言:javascript
复制
var t int
var x interface{}
x = t
y = x.(int)  //转成int  
或 y ,ok  = x.(int) //转成int,带检查

判断一个变量是否实现了某个接口,可以用
var v MyStruct
var f interface{}
f = v
if sv,ok := f.(Stringer){

}

还有这个:

代码语言:javascript
复制
swithc x.(type){

}

  • 反射:可以在运行时动态获取变量的相关信息

Import("reflect") 相关函数: a. reflect.TypeOf,获取变量的类型返回reflect.Type类型 b. reflect.ValueOf ,获取变量的值,返回reflect.Value类型 c. reflect.Value.Kind 获取变量的类别(如返回struct),返回一个常量,注意类别类型的区别 d. reflect.Value.Interface,转换interface{}类型

用反射操作结构体: a. relect.Value.NumField() 获取结构体中字段的个数 b. relect.Value.Method(n).Call来调用结构体中的方法


终端读写: 操作终端相关的句柄常量:

  • os.Stdin: 标准输入 (键盘等)
  • os.Stdout:标准输出(控制台等)
  • os.Stderr:标准错误
  • Sscanf可以中字符串中获取空格分隔
  • 带缓冲区的读写 bufio
  • 关闭一个文件 defer file.Close()

Errorf和error.New


  • 进程是资源分配和调度的独立单位
  • 线程是CPU调度和分派的基本单位
  • 一个进程可以创建和撤销多个线程,同一进程中的多个线程可以并发执行

并发和并行的区别:

  • 多线程程序在一个核的CPU上运行,就是并发
  • 多线程程序在多核CPU上运行,就是并行

协程和线程:

  • 协程: 独立的栈空间,共享堆空间,调度由用户自己控制,本质上有点类似于用户级线程,这些用户级线程的调度由自己实现的
  • 线程:一个线程上可以跑多个协程,协程是轻量级线程。

  • 协程并行访问全局变量时,需要给全局变量加锁

channel:

  • 类似于unit中的管道(pipe)
  • 先进先出
  • 线程安全,多个goroutine同时访问,不需要加锁
  • channel是有类型的,一个整数类型的channel只能存放整数
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-12-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 2.读写锁 Rwmutex
  • 结构体是用户单独定义的类型,不能和其他类型进行强制转换。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档