Go二三事
Go认为方法是添加了受限作用域类型的函数。杂谈空结构体,空接口,指针类型强转,数组类型的哈希键等琐事。
receiver
Go称之如下格式的函数为方法,recv
为接收者变量
func (recv receiver_type) methodName(parameter_list) (return_value_list) { … }
换而言之,若方法体内用不到类似其它语言中的this
变量,可以这样干,但接收者类型不可略。
func (receiver_type) methodName(parameter_list) (return_value_list) { … }
receiver_type
可以是任意类型,不仅仅是结构体类型
可以是接口类型,甚至是函数,int,bool,string,array
的别名类型
package main
import "fmt"
type multiply int
func (m multiply) tentimes() int {
return int(m * 10)
}
func main() {
var num int
fmt.Print("Enter any positive integer: ")
fmt.Scanln(&num)
mul:= multiply(num)
fmt.Println("Ten times of a given number is: ",mul.tentimes())
}
overloading
Go语言的方法重载是基于接收者类型的,以下这种形式是允许存在于同一包内
func (s *inclTax) Salary(e Employee) Employee
func (s *exclTax) Salary(e Employee) Employee
type
类型检查
i := 10
reflect.TypeOf(i) // int
strconv
将字符串转为基本数据类型
其它可兼容类型直接 type()
强转,或基于接口变量的类型断言 .(type)
指针类型强转有点特殊,需要用到unsafe.Pointer
来解除指针在go中不可运算的限制。
package main
import (
"fmt"
"unsafe"
)
type A struct {
name string
age int8
}
type B struct {
notname string
notage int8
sex int8
}
func main() {
b := &B{notname: "B", notage: 28, sex: 1}
a := (*A)(unsafe.Pointer(b))
fmt.Println(a.name) // B
}
interface vs struct
interface
与 struct
都是Go关键字,用来辅助定义数据类型
- struct 各个字段类型集合体,本质是个具体值类型,可用作 map 键
- interface 准确来说是个函数列表集成器,玩虚的,隐藏实现,具备行为截断
换而言之,接口未实现不可用,实现了该接口的变量也实现了(若存在)嵌套接口
struct{}
宽度描述了存储一个数据类型实例需要占用的字节数
空结构体类型是没有位段的结构体,换而言之它不占用内存空间
var p struct{}
var s string
fmt.Println(unsafe.Sizeof(p)) // prints 0
fmt.Println(unsafe.Sizeof(s)) // prints 8
基于这些特性,常有以下应用场景
- 空结构体作为方法的接收者
- 空结构体写入
chan
通道,作为触发器,用其他冗余数据的话,会影响程序性能
interface{}
与空结构体类型表示什么都没有,空接口类型简而言之什么都是
空接口interface{}
比之如java
界的 object
, 类似python
中的 type
类型。
在什么都是的情况下,看起来高大上,实际上沦为了工具,基本上就是成了容器,类js解构
func Printf(format string, a ...interface{}) (n int, err error)
这种类型不能直接读写,需要断言存取实际具体类型,只不过传输时看起来无所不能。
type Context interface {
Deadline() (deadline time.Time, ok bool)
Done() <-chan struct{}
Err() error
Value(key interface{}) interface{}
}
const
Go中的常量通常与数组合体使用,如同结构体一样,作为值类型的数组也可作为哈希类型的键。
示例 字母异位词分组,达成效果
输入: ["eat", "tea", "tan", "ate", "nat", "bat"]
输出:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
实现代码,Go中 数组是带有固定长度信息的值类型,可为哈希键。
func groupAnagrams(strs []string) [][]string {
const N = 26
m := make(map[[N]int][]string,0)
for _, str := range strs {
cnt := [N]int{}
for _, v := range str {
cnt[v - 'a']++
}
m[cnt] = append(m[cnt], str)
}
rs := make([][]string,0,len(m))
for _, v := range m {
rs = append(rs, v)
}
return rs
}
compare
在Go通常意义上值类型都可使用比较操作,指针类型不行,哪怕类型内容相同仍然为false
切片类型不可用==
操作符比较(与nil
比较除外),但数组,结构体值类型都可比,当然比较基础是类型相同。
arr :=[2]int{1,2}
brr :=[2]int{1,2}
fmt.Println(arr == brr) // true
type A struct{
name string
age int
}
aa := A{"pardon",20}
bb := A{"pardon",20}
fmt.Println(aa == bb) // true
other
通常Go
出于类型系统和内存管理的安全机制考虑,编译器会对所有指针类型转换或运算报错,
但凡事没绝对,有时的确有突破这方面的需求,故提供了 unsafe.Pointer
包,一切操作都是可行。
本作品采用《CC 协议》,转载必须注明作者和本文链接