Design principle behind just two built-in data structures

Hi forum,

  1. Go provides just two built-in data structures including slice and map. It has more than C (just array) but less than Python, C++ and Swift. I think this is great and makes everyone’s code kind of look familiar. But I still wonder what is the mind behind the design of the two member built-in data structures.

  2. Why it does not require some kind of Hash or Equal interfaces, when I want to check if a key of type of custom struct is in a map? For example, if I’m going to sort slice of custom struct, I’ll need to define Len, Less, Swap of sort.

Thanks

package main

import (
	"fmt"
)

type K struct {
	name string
	num  int
}

func main() {
	d := map[K]struct{}{}
	d[K{"ccc", 3}] = struct{}{}
	d[K{"bbb", 2}] = struct{}{}
	d[K{"aaa", 1}] = struct{}{}

	k := K{"bbb", 2}
	v, ok := d[k]
	fmt.Println(v, ok)  //true
}

Hi @ljh,

  1. I think the main design principle here is minimalism. Basic types, arrays/slices, maps, structs, and interfaces are pretty much all you need to build more complex data structures.

    I don’t know off the top of my head what types Python or Swift provide in addition to maps and (dynamic) arrays, but I bet these types can be expressed with Go’s built-in types with minimal effort. Hence there would be no compelling reason to include them in the core language.

  2. Map keys must be comparable types. That is, only those types that have == and != operators defined can be used as a map key. Therefore, no extra language construct is needed to test if a key exists in a map.

    Slices, on the other hand, can hold any kind of data. Unlike maps, slices have no reason to restrict element types to be sortable types. Hence, if you want to sort a slice with custom element types, you have to implement your own sorting algorithm. the Len/Less/Swap interface helps you to do that.

1 Like

Thanks Christoph,

I just figured out that those two operators are defined for structs, but less or greater than are not. structs are not comparable by default in C++ though.

type K struct {
	name string
	num  int
}

func main() {
	k1 := K{"bbb", 2}
	k2 := K{"bbb", 2}

	fmt.Println("k1 == k2", k1 == k2) //true
	fmt.Println("k1 != k2", k1 != k2) //false
	// fmt.Println("k1 < k2", k1 < k2) //not defined
	// fmt.Println("k1 > k2", k1 > k2) //not defined
}

That’s correct, but this depends on the struct’s fields. If you add a field that is not comparable, the struct as a whole is not comparable anymore.

1 Like

Thanks Christoph

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.