《The.Go.Programming.Language.2015.11.pdf》之map和结构体

本文详细介绍了Go语言中的map和struct。map作为一种哈希表,允许安全地访问不存在的key并返回零值,不可取map的地址,可以通过迭代进行遍历。struct的定义与成员访问方式包括直接访问和通过指针访问,大写字母开头的成员对外可见。文中还讨论了如何比较两个map以及使用map实现图和统计Unicode字符的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

map

在go语言中,map是一个hash 表的引用。
map的声明

    ages := make(map[string]int) // mapping from strings to ints

    ages := map[string]int{
        "alice":   31,
        "charlie": 34,
    }

元素的访问

    ages["alice"] = 32
    fmt.Println(ages["alice"]) // "32"

删除元素

    delete(ages, "alice") // remove element ages["alice"]

即使key不存在,所有上面的这些操作都是安全的。在go语言中,查找一个不存在的key对应的值,返回值类型的0值。
所以下面的操作即使bob不是ages的key,仍然代码是没有问题的,因为程序在第一次访问map["bob"]的时候返回0.

    ages["bob"] = ages["bob"] + 1 // happy birthday!

在go语言中不能取map的地址,因为随着数据长度的增加,map的数据可能会转移,所以地址会改。

遍历map

    for name, age := range ages {
        fmt.Printf("%s\t%d\n", name, age)
    }

判断key是否存在

    if age, ok := ages["bob"]; !ok { /* ... */
    }

判断两个map是否相同只能自己实现

func equal(x, y map[string]int) bool {
    if len(x) != len(y) {
        return false
    }
    for k, xv := range x {
        if yv, ok := y[k]; !ok || yv != xv {
            return false
        }
    }
    return true
}

统计unicode字符

func main() {
    counts := make(map[rune]int)
    // counts of Unicode characters
    var utflen [utf8.UTFMax + 1]int // count of lengths of UTF-8 encodings
    invalid := 0
    // count of invalid UTF-8 characters
    in := bufio.NewReader(os.Stdin)
    for {
        r, n, err := in.ReadRune() // returns rune, nbytes, error
        if err == io.EOF {
            break
        }
        if err != nil {
            fmt.Fprintf(os.Stderr, "charcount: %v\n", err)
            os.Exit(1)
        }
        if r == unicode.ReplacementChar && n == 1 {
            invalid++
            continue
        }
        counts[r]++
        utflen[n]++
    }
    fmt.Printf("rune\tcount\n")
    for c, n := range counts {
        fmt.Printf("%q\t%d\n", c, n)
    }
    fmt.Print("\nlen\tcount\n")
    for i, n := range utflen {
        if i > 0 {
            fmt.Printf("%d\t%d\n", i, n)
        }
    }
    if invalid > 0 {
        fmt.Printf("\n%d invalid UTF-8 characters\n", invalid)
    }
}

利用map实现图
map的值类型可以也是map类型,下面代码例子中,graph的key类型是string,值类型是map[string]bool,表示一个string列表。

var graph = make(map[string]map[string]bool)

func addEdge(from, to string) {
    edges := graph[from]
    if edges == nil {
        edges = make(map[string]bool)
        graph[from] = edges
    }
    edges[to] = true
}
func hasEdge(from, to string) bool {
    return graph[from][to]
}

Structs

定义

type Employee struct {
    ID        int
    Name      string
    Address   string
    DoB       time.Time
    Position  string
    Salary    int
    ManagerID int
}

var dilbert Employee

成员访问

可以利用.来访问结构体中的域成员。

dilbert.Salary -= 5000

也可以通过地址访问

position := &dilbert.Position
*position = "Senior " + *position // promoted, for outsourcing to Elbonia

对于结构体的指针也可以使用.来访问成员

var employeeOfTheMonth *Employee = &dilbert
employeeOfTheMonth.Position += " (proactive team player)"

结构体的域的名称如果是以大写开头的,表示这个成员是可以外部访问的。

package p
type T struct{ a, b int } // a and b are not exported
package q
import "p"
var _ = p.T{a: 1, b: 2} // compile error: can't reference a, b
var _ = p.T{1, 2}
// compile error: can't reference a, b

如果结构体的所有域都是可以比较的,那么这个结构体也是可以比较的。

type Point struct{ X, Y int }
p := Point{1, 2}
q := Point{2, 1}
fmt.Println(p.X == q.X && p.Y == q.Y) // "false"
fmt.Println(p == q)
// "false"
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值