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

interfacestruct 都是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 协议》,转载必须注明作者和本文链接
pardon110
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
开发者 @ 社科大
文章
134
粉丝
24
喜欢
101
收藏
55
排名:106
访问:8.9 万
私信
所有博文
社区赞助商