美文网首页
GO - data structures

GO - data structures

作者: 隐号骑士 | 来源:发表于2024-12-20 23:23 被阅读0次

Official ref: https://go.dev/ref/spec#Types

basic datatypes are Value Types: e.g. int boolean string array struct ...
reference datatypes are:

  • Slice
  • Map
  • Channel
  • Pointer
  • Interface

Slice

https://github.com/golang/go/blob/master/src/runtime/slice.go

type slice struct {
    array unsafe.Pointer
    len   int
    cap   int
}
+------------+------------+------------+
|   Pointer  |   Length   |  Capacity  |
+------------+------------+------------+
       |            |            |
       V            V            V
   [underneath array] ---> [1, 2, 3]

When dynamic expansion:
Basically, it allocates another space from memory and copies all the existing data from the old slice to the new slice, so the pointer of slice should change as well

package main

import "fmt"

func main() {
    slice := []int{1, 2, 3}
    fmt.Println("Init:")
    fmt.Printf("slice: %v, len: %d, cap: %d, address: %p\n", slice, len(slice), cap(slice), &slice[0])

    slice[0] = 2
    fmt.Println("\nAfter modify:")
    fmt.Printf("slice: %v, len: %d, cap: %d, address: %p\n", slice, len(slice), cap(slice), &slice[0])

    slice = append(slice, 4)
    fmt.Println("\nAfter append:")
    fmt.Printf("slice: %v, len: %d, cap: %d, address: %p\n", slice, len(slice), cap(slice), &slice[0])
}

output:

Init:
slice: [1 2 3], len: 3, cap: 3, address: 0x14000016138

After modify:
slice: [2 2 3], len: 3, cap: 3, address: 0x14000016138

After append:
slice: [2 2 3 4], len: 4, cap: 6, address: 0x14000020120

Map

Actually hashmap
https://github.com/golang/go/blob/go1.21.0/src/runtime/map.go

// A header for a Go map.
type hmap struct {
    // Note: the format of the hmap is also encoded in cmd/compile/internal/reflectdata/reflect.go.
    // Make sure this stays in sync with the compiler's definition.
    count     int // # live cells == size of map.  Must be first (used by len() builtin)
    flags     uint8
    B         uint8  // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
    noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details
    hash0     uint32 // hash seed

    buckets    unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
    oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
    nevacuate  uintptr        // progress counter for evacuation (buckets less than this have been evacuated)

    extra *mapextra // optional fields
}
package main

import (
    "fmt"
)

func main() {
    m := map[string]int{
        "a": 1,
        "b": 2,
        "c": 3,
    }
    fmt.Printf("%v\n", m)
    m["d"] = 4
    fmt.Printf("%v\n", m)
    delete(m, "a")
    fmt.Printf("%v\n", m)

    for key, value := range m {
        fmt.Printf("%v\n", key)
        fmt.Printf("%v\n", value)
    }
    clear(m)
    fmt.Printf("%v\n", m)
}

output:

map[a:1 b:2 c:3]
map[a:1 b:2 c:3 d:4]
map[b:2 c:3 d:4]
b
2
c
3
d
4
map[]

Also there is mechanism of dynamic expansion for map. However, I couldn't demostrate it by code so far, since map does not expose any of the internal pointers to user.

Interface

type iface struct {
    tab  *itab
    data unsafe.Pointer
}
type itab struct {
    inter  *interfacetype
    _type  *_type
    link   *itab
    hash   uint32 // copy of _type.hash. Used for type switches.
    bad    bool   // type does not implement interface
    inhash bool   // has this itab been added to hash?
    unused [2]byte
    fun    [1]uintptr // variable sized
}

dynamic type and dynamic value:

package main

import "fmt"

type Speaker interface {
    Speak()
}

type Person struct {
    Name string
}

func (p Person) Speak() {
    fmt.Println("My name is", p.Name)
}

func main() {
    var speaker Speaker

    p := Person{Name: "Alice"}

    speaker = p

    speaker.Speak() // output: My name is Alice
}

empty interface:

package main

import "fmt"

func printValue(i interface{}) {
    fmt.Println(i)
}

func main() {
    printValue(42)         // output:42
    printValue("hello")    // output:hello
    printValue(3.14)       // output:3.14
}

Channel

package main

import "fmt"

func main() {
    ch := make(chan int, 3)
    ch <- 42
    ch <- 41
    ch <- 40
    value := <-ch
    fmt.Print(value)
    ch <- 29
    value1 := <-ch
    fmt.Print(value1)
    value2 := <-ch
    fmt.Print(value2)
    value3 := <-ch
    fmt.Print(value3)
}
package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int)

    go func() {
        fmt.Println("Sending data to channel")
        ch <- 42
        fmt.Println("Data sent")
    }()

    fmt.Println("Receiving data from channel")
    value := <-ch
    fmt.Println("Received:", value)
}

output:

Receiving data from channel
Sending data to channel
Data sent
Received: 42

Pointer

相关文章

网友评论

      本文标题:GO - data structures

      本文链接:https://www.haomeiwen.com/subject/icusejtx.html