Go 语言的冷知识

2,426 阅读4分钟
原文链接: zhuanlan.zhihu.com

append, map, len不是关键字

他们其实还是类库功能, 都在builtin包里的, 系统默认给你做了个

将builtin的包内容都映射到全局而已, 其实你也可以用自己的包这么做

打印的另一种写法

想跟脚本一样调试打印数据么?

无需包含任何包, 因为它在builtin包里

iota不是黑科技

这是在builtin包里的定义

// iota is a predeclared identifier representing the untyped integer ordinal
// number of the current const specification in a (usually parenthesized)
// const declaration. It is zero-indexed.
const iota = 0 // Untyped int.

其实go是有泛型概念的

想想map和数组的定义
只是泛型没有开放给用户用而已(只许XX放火,不许XX点灯)

map是支持多个key的, 而且很方便

还在为多个key转id的复杂算法而头疼么?

type myKey struct{
    number int
    str string
}

func main(){
    t := map[ myKey] int {
        myKey{ 2, "world"}: 1,
    }
    fmt.Println(t[myKey{2, "world"}])
}

输出: 1

枚举是可以转成string的

默认定义一个枚举

type MyConst int

const (
    MyConst_A MyConst = iota
    MyConst_B MyConst = iota
)

func main(){
    fmt.Println(MyConst_A)
}

输出: 0
如果我们想自动化输出MyConst_A字符串时
就需要使用golang的一个工具链:http://golang.org/x/tools/cmd/stringer
将其下载, 编译成可执行工具后, 对代码进行生成
生成的代码会多出一个xx_string.go
里面就是枚举的String()string 函数

临时转换一个接口并调用的方法

type love struct{
}

func (self*love)foo(){
    fmt.Println("love")
}

func main(){
    var chaos interface{} = new(love)
    chaos.(interface{
        foo()
    }).foo()
}

Golang的receiver实际上就是this的变种实现

func( self*MyStruct) foo( p int ){
}

写不惯receiver的写法? 如果这样改下呢?

func foo( self *MyStruct, p int ){
}

所以为什么说Golang还是一个C语言嘛

关于内存分配…

  • new 传入Type类型, 返回*Type类型
  • make 可以在分配数组时设置预分配大小, new不可以
  • make 能分配数组,map, 但不能分配结构体和原始类型
  • new 能分配数组, map, 结构体和原始类型等的所有类型
  • &Type等效于new
  • 切片不需要分配内存(make,new), 直接声明就可以了…

Golang的反射无法通过一个类型名, 创建其实例

C#有Assembly概念, 可以在一个Assembly里搜索, 创建实例

Golang是静态类型语言, 如果需要, 只能注册你需要创建的结构体, 然后将注册好的map用于创建

Golang可以替换Python来进行复杂的工具流程处理

如果你需要跨平台的工具流程处理, 对Python不熟悉, 可以使用

go run yourcode.go 参数1 参数2

方式来进行工具处理
觉得慢, 可以编译成可执行文件

这样做的好处: 如果有些类库本身就是go写的, Python想使用是很麻烦的, 而Golang来写则轻而易举

例子: 通过go的protobuf库, 对一些文件进行处理

Golang可以自动持有方法的接收者实例

type myType struct{
}

func (self*myType) foo( p int){
    fmt.Println("hello", p )
}

func main(){
    var callback func( int )
    ins := new(myType)
    callback = ins.foo
    callback( 100 )
}

做过lua的C++代码绑定的童鞋都清楚: lua只支持外部静态或者全局函数调用
如果要进行C++类成员函数调用时, 要自己处理this和成员函数
这种技巧因为早起编译器的虚表不同平台实现细节不统一需要专门处理
后面跨平台虚表统一后, 类成员函数的调用写法也是很恶心复杂的
但是Golang的小白式用法, 直接吊打C++, 甚至C#复杂的delegate

LiteIDE篇: 多开秘籍

  • 找到 菜单->查看->选项->通用->存储->存储设置到本地ini文件

  • 关闭LiteIDE

  • 复制LiteIDE整个目录, 命名文件夹为你的工程名

  • 每个工程所在的LiteIDE的配置将是独立的, 不会互相干扰

LiteIDE篇: 测试程序也是可以调试的

别以为程序一定要是main开始的才可以调试

Golang的测试程序虽然都是一个个Test开头的函数,但执行go test时, 还是有main入口

在LiteIDE中, 可以在 调试->开始调试测试程序里进行测试程序调试

LiteIDE篇: 在Windows上可以输出linux可执行文件

go的工具链默认支持交叉编译
在LiteIDE中, 可以通过切换输出平台, 输出不同平台的可执行文件