Check operation on data types (basic type, composite type, reference type, type conversion [cast])

There are several types of data types in Go: basic (int / float / bool / string / rune / byte), composite (array / struct), and reference (slice / map / pointer / channel / function). In this section, we will execute a simple process for each data type to check its operation.

TOC

Basic Type

int

package main

import (
	"fmt"
)

func main() {
	var (
		i1 int    = 10  // signed, depends on execution architecture (32bit or 64bit)
		i2 int    = 1e9 // 9 to the power of 10(=1000000000)
		i3 int16  = 10  // signed min:-32768 max:32767
		i4 int32  = 10  // signed min:-2147483648 max:2147483647 (about 2 billion)
		i5 int64  = 10  // signed min:-9223372036854775808 max:9223372036854775807
		i6 uint   = 10  // unsigned depends on execution architecture (32bit or 64bit)
		i7 uint32 = 10  // unsigned min:0 max:4294967295 (about 4 billion)
	)
	fmt.Printf("%T %T %T %T %T %T %T\n", i1, i2, i3, i4, i5, i6, i7)
}
int int int16 int32 int64 uint uint32

float

package main

import (
	"fmt"
)

func main() {
	var (
		f32 float32 = 1.11111111111111111
		f64 float64 = 1.11111111111111111
	)
	fmt.Printf("%T\n", f32)
	fmt.Println(f32)
	fmt.Printf("%T\n", f64)
	fmt.Println(f64)
}
float32
1.1111112
float64
1.1111111111111112

bool

package main

import (
	"fmt"
)

func main() {
	var (
		t bool = true
		f bool = false
	)

	fmt.Printf("%T\n", t)
	fmt.Println(t)
	fmt.Printf("%T\n", f)
	fmt.Println(f)
}
bool
true
bool
false

string

package main

import (
	"fmt"
)

func main() {
	var (
		s1 string = "わくわくBank"   // Enclose in double quotation marks

		// Here Documents (enclosed in backquotes)
		s2 string = `Hello
World`
	)

	fmt.Printf("%T\n", s1)
	fmt.Println(s1)
	fmt.Println(s2)
	fmt.Println(len(s1))
	for i, v := range s1 {
		// Using the range syntax, you can get the rune by rune.
		//   Each letter of the alphabet is one byte.
		//   Japanese is almost 3 bytes per character.
		fmt.Printf("%T i:%v v:%v\n", v, i, v)
	}
	fmt.Printf("s[12]: %v\n", s1[12])
	fmt.Printf("[]rune(s): %v\n", []rune(s1))
	fmt.Printf("[]byte(s): %v\n", []byte(s1))
}
string
わくわくBank
Hello
World
16
int32 i:0 v:12431
int32 i:3 v:12367
int32 i:6 v:12431
int32 i:9 v:12367
int32 i:12 v:66
int32 i:13 v:97
int32 i:14 v:110
int32 i:15 v:107
s[12]: 66
[]rune(s): [12431 12367 12431 12367 66 97 110 107]
[]byte(s): [227 130 143 227 129 143 227 130 143 227 129 143 66 97 110 107]

rune

package main

import (
	"fmt"
)

func main() {
	var (
		r1 rune = 97
		r2 rune = 'a' // Single Quarto handles Rune type.
	)
	fmt.Printf("%T\n", r1)
	fmt.Println(r1)
	fmt.Println(string(r1))

	fmt.Printf("%T\n", r2)
	fmt.Println(r2)
	fmt.Println(string(r2))
}
int32
97
a
int32
97
a

byte

package main

import (
	"fmt"
)

func main() {
	var (
		b byte = 97
	)
	fmt.Printf("%T\n", b)
	fmt.Println(b)
	fmt.Println(string(b))
}
uint8
97
a

Composite Type

Array

The number of array elements is fixed. If you want to add elements, use slices.

package main

import "fmt"

func main() {
	var array1 [2]string
	array1[0] = "aaa"
	array1[1] = "bbb"
	fmt.Printf("%T\n", array1)
	fmt.Println(array1[0], array1[1])
	fmt.Println(array1)
	fmt.Println(len(array1))
	fmt.Println("-----------------------")

	array2 := [4]int{1, 2, 3, 4}
	fmt.Printf("%T\n", array2)
	fmt.Println(array2)
	fmt.Println("-----------------------")

	array3 := [...]int{1, 2, 3, 4}
	fmt.Printf("%T\n", array3)
	fmt.Println(array3)
}
[2]string
aaa bbb
[aaa bbb]
2
-----------------------
[4]int
[1 2 3 4]
-----------------------
[4]int
[1 2 3 4]

Struct

package main

import "fmt"

type User struct {
	ID    int
	Name  string
	age   int // Leading lowercase letters are private
	Score int
}

func main() {
	u1 := User{}
	fmt.Printf("%T\n", u1)
	fmt.Println(u1)

	u2 := User{1, "yamada", 30, 100}
	fmt.Printf("%T\n", u2)
	fmt.Println(u2)

	u2.Name = "suzuki"
	u2.age = 31 // Can be updated from the same package
	fmt.Println(u2)

	// Update value via structure pointer
	p := &u2
	p.age = 32
	fmt.Printf("%T\n", p)
	fmt.Println(p)
	fmt.Println(u2)
}
main.User
{0  0 0}
main.User
{1 yamada 30 100}
{1 suzuki 31 100}
*main.User
&{1 suzuki 32 100}
{1 suzuki 32 100}

Reference Type

Slice

When cap (capacity=capacity) changes occur, memory space is reclaimed, which increases processing costs.

package main

import "fmt"

func main() {
	s1 := []int{1, 2, 3, 4, 5, 6, 7, 8}
	fmt.Printf("type: %T\n", s1)
	fmt.Printf("len:%d cap:%d v:%v\n", len(s1), cap(s1), s1)

	s1 = s1[:0]
	fmt.Printf("len:%d cap:%d v:%v\n", len(s1), cap(s1), s1)

	s1 = s1[:2]
	fmt.Printf("len:%d cap:%d v:%v\n", len(s1), cap(s1), s1)

	s1 = s1[:4]
	fmt.Printf("len:%d cap:%d v:%v\n", len(s1), cap(s1), s1)

	s1 = s1[2:]
	fmt.Printf("len:%d cap:%d v:%v\n", len(s1), cap(s1), s1)

	s1 = s1[:4]
	fmt.Printf("len:%d cap:%d v:%v\n", len(s1), cap(s1), s1)

	s1 = append(s1, 1, 2)
	fmt.Printf("len:%d cap:%d v:%v\n", len(s1), cap(s1), s1)

	s1 = append(s1, 3)
	fmt.Printf("len:%d cap:%d v:%v\n", len(s1), cap(s1), s1)
	fmt.Println("----------------------------------------")

	// Generate slice by make
	s2 := make([]int, 5, 10)
	fmt.Printf("type: %T\n", s2)
	fmt.Printf("len:%d cap:%d v:%v\n", len(s2), cap(s2), s2)
	fmt.Println("----------------------------------------")

	s3 := make([]int, 5)
	fmt.Printf("type: %T\n", s3)
	fmt.Printf("len:%d cap:%d v:%v\n", len(s3), cap(s3), s3)
	fmt.Println("----------------------------------------")

	s4 := make([]int, 0, 10)
	fmt.Printf("type: %T\n", s4)
	fmt.Printf("len:%d cap:%d v:%v\n", len(s4), cap(s4), s4)
}
type: []int
len:8 cap:8 v:[1 2 3 4 5 6 7 8]
len:0 cap:8 v:[]
len:2 cap:8 v:[1 2]
len:4 cap:8 v:[1 2 3 4]
len:2 cap:6 v:[3 4]
len:4 cap:6 v:[3 4 5 6]
len:6 cap:6 v:[3 4 5 6 1 2]
len:7 cap:12 v:[3 4 5 6 1 2 3]
----------------------------------------
type: []int
len:5 cap:10 v:[0 0 0 0 0]
----------------------------------------
type: []int
len:5 cap:5 v:[0 0 0 0 0]
----------------------------------------
type: []int
len:0 cap:10 v:[]

Multidimensional Slice

package main

import "fmt"

func main() {
	s1 := [][]int{
		{1, 2, 3},
		{1, 2, 3, 4, 5, 6, 7, 8},
	}
	fmt.Printf("type: %T\n", s1)
	fmt.Printf("len:%d cap:%d v:%v\n", len(s1), cap(s1), s1)

	s1 = append(s1, []int{1, 2})
	fmt.Printf("len:%d cap:%d v:%v\n", len(s1), cap(s1), s1)
}
type: [][]int
len:2 cap:2 v:[[1 2 3] [1 2 3 4 5 6 7 8]]
len:3 cap:4 v:[[1 2 3] [1 2 3 4 5 6 7 8] [1 2]]

Map

package main

import "fmt"

func main() {
	var m1 map[string]int
	fmt.Printf("%T\n", m1)

	fmt.Println("----------------------")
	fmt.Println(m1)
	// If only a var declaration is used, the content is nil.
	fmt.Printf("m1 == nil: %v\n", m1 == nil)
	// Setting availability can be determined by len
	fmt.Printf("len(m1): %v\n", len(m1))

	fmt.Println("----------------------")
	// Using make takes up memory space.
	m1 = make(map[string]int)
	fmt.Println(m1)
	fmt.Printf("m1 == nil: %v\n", m1 == nil)
	fmt.Printf("len(m1): %v\n", len(m1))
	fmt.Println("----------------------")

	m1["aaa"] = 1
	m1["bbb"] = 2
	m1["ccc"] = 3
	fmt.Println(m1)
	fmt.Printf("len(m1): %v\n", len(m1))
	fmt.Println("----------------------")

	delete(m1, "bbb")
	fmt.Println(m1)
	fmt.Println("----------------------")

	_, ok1 := m1["bbb"]
	fmt.Println(ok1)
	_, ok2 := m1["ccc"]
	fmt.Println(ok2)
}
map[string]int
----------------------
map[]
m1 == nil: true
len(m1): 0
----------------------
map[]
m1 == nil: false
len(m1): 0
----------------------
map[aaa:1 bbb:2 ccc:3]
len(m1): 3
----------------------
map[aaa:1 ccc:3]
----------------------
false
true

Combination notes for Map and Struct ( Cannot assign to xxx )

When Struct is stored in Map, it is not possible to update the elements of Struct while it is stored in Map.

package main

import "fmt"

type sampleStruct struct {
	x int
}

func main() {
	sampleMap := make(map[int]sampleStruct, 1)
	sampleMap[0] = sampleStruct{x: 100}

	// sampleMap[0].x: 100
	fmt.Printf("sampleMap[0].x: %d\n", sampleMap[0].x)

	// The following is "Cannot assign to sampleMap[0].x".
	// sampleMap[0].x = 200

	// It must be taken out once as follows
	sm := sampleMap[0]
	sm.x = 200
	sampleMap[0] = sm
	
	// sampleMap[0].x: 200
	fmt.Printf("sampleMap[0].x: %d\n", sampleMap[0].x)
}

Multidimensional Map

package main

import "fmt"

func main() {
	var m2 map[string]map[string]int
	m2 = make(map[string]map[string]int)
	fmt.Printf("%T\n", m2)
	fmt.Println(m2)
	fmt.Println("----------------------")

	// The following error occurs (panic: assignment to entry in nil map). Because m2["aaa"] is nil.
	// m2["aaa"]["xxx"] = 1

	if _, ok := m2["aaa"]; !ok {
		m2["aaa"] = make(map[string]int)
		m2["aaa"]["xxx"] = 1
		m2["aaa"]["yyy"] = 2
		m2["aaa"]["zzz"] = 3
	}
	fmt.Println(m2)
}
map[string]map[string]int
map[]
----------------------
map[aaa:map[xxx:1 yyy:2 zzz:3]]

We also see alternative methods such as using a concatenated string of key strings as the key to avoid a multidimensional map.

Pointer

package main

import "fmt"

func main() {
	var p *int // Pointer type pointing to int.
	fmt.Printf("%T\n", p)
	fmt.Println(p)

	i := 100
	p = &i

	fmt.Println("-----------------------")
	fmt.Println(p)
	fmt.Println(*p)
	fmt.Println(i)
	fmt.Println(&i)

	*p = 200
	fmt.Println("-----------------------")
	fmt.Println(p)
	fmt.Println(*p)
	fmt.Println(i)
	fmt.Println(&i)

	i = 300
	fmt.Println("-----------------------")
	fmt.Println(p)
	fmt.Println(*p)
	fmt.Println(i)
	fmt.Println(&i)
}
*int
<nil>
-----------------------
0xc0000160a0
100
100
0xc0000160a0
-----------------------
0xc0000160a0
200
200
0xc0000160a0
-----------------------
0xc0000160a0
300
300
0xc0000160a0

Channel

Channel can be utilized to exchange data with functions running concurrently in goroutine.

package main

import (
	"fmt"
	"sync"
	"time"
)

// <-chan int: read only
func receivePrint(name string, c <-chan int, wg *sync.WaitGroup) {
	for {
		time.Sleep(1000 * time.Millisecond)
		i, ok := <-c
		fmt.Printf("[Receive]\tname: %v\tcap: %v\tlen: %v\ti: %v\tok: %v\n", name, cap(c), len(c), i, ok)
		if ok == false {
			break
		}
	}
	fmt.Printf("[Done]\t\tname: %v\n", name)
	wg.Done()
}

func main() {
	var wg sync.WaitGroup

	// Channels with a buffer size of 5
	c := make(chan int, 5)
	fmt.Printf("%T\n", c)
	fmt.Println(c)

	wg.Add(2)
	go receivePrint("1st", c, &wg)
	go receivePrint("2nd", c, &wg)

	for i := 0; i < 10; i++ {
		c <- i
		fmt.Printf("[Send]\t\tname: main\tcap: %v\tlen: %v\n", cap(c), len(c))
	}
	close(c)
	wg.Wait()
	fmt.Println("[Done]\t\tname: main")
}
chan int
0xc000112000
[Send]          name: main      cap: 5  len: 1
[Send]          name: main      cap: 5  len: 2
[Send]          name: main      cap: 5  len: 3
[Send]          name: main      cap: 5  len: 4
[Send]          name: main      cap: 5  len: 5
[Send]          name: main      cap: 5  len: 4
[Send]          name: main      cap: 5  len: 5
[Receive]       name: 1st       cap: 5  len: 4  i: 1    ok: true
[Receive]       name: 2nd       cap: 5  len: 5  i: 0    ok: true
[Receive]       name: 2nd       cap: 5  len: 5  i: 2    ok: true
[Send]          name: main      cap: 5  len: 4
[Send]          name: main      cap: 5  len: 5
[Receive]       name: 1st       cap: 5  len: 4  i: 3    ok: true
[Receive]       name: 2nd       cap: 5  len: 5  i: 4    ok: true
[Receive]       name: 1st       cap: 5  len: 4  i: 5    ok: true
[Send]          name: main      cap: 5  len: 4
[Receive]       name: 1st       cap: 5  len: 3  i: 6    ok: true
[Receive]       name: 2nd       cap: 5  len: 2  i: 7    ok: true
[Receive]       name: 2nd       cap: 5  len: 1  i: 8    ok: true
[Receive]       name: 1st       cap: 5  len: 0  i: 9    ok: true
[Receive]       name: 2nd       cap: 5  len: 0  i: 0    ok: false
[Done]          name: 2nd
[Receive]       name: 1st       cap: 5  len: 0  i: 0    ok: false
[Done]          name: 1st
[Done]          name: main

Function

package main

import "fmt"

func main() {
	f := func(x int) {
		fmt.Println("hello world '", x, "'.")
	}
	f(1)
	fmt.Printf("%T\n", f)
	fmt.Println(f)
}
hello world ' 1 '.
func(int)
0x10a8b80

interface{}

interface{} is a type compatible with any type.

package main

import (
	"fmt"
)

func printInterface(i interface{})  {
	fmt.Printf("%v[%T]\n", i, i)

	switch v := i.(type) {
	case int:
		fmt.Printf("%v is int[%T]\n", v, v)
	case string:
		fmt.Printf("%v is string[%T]\n", v, v)
	default:
		fmt.Printf("default: %v[%T]\n", v, v)
	}
}

func main() {
	var i interface{}
	fmt.Printf("%v[%T]\n", i, i)

	fmt.Println("-----------------------------")
	i = "hello"
	fmt.Printf("%v[%T]\n", i, i)
	printInterface(i)

	fmt.Println("-----------------------------")
	i = 100
	fmt.Printf("%v[%T]\n", i, i)
	printInterface(i)

	fmt.Println("-----------------------------")
	i = true
	fmt.Printf("%v[%T]\n", i, i)
	printInterface(i)
}
<nil>[<nil>]
-----------------------------
hello[string]
hello[string]
hello is string[string]
-----------------------------
100[int]
100[int]
100 is int[int]
-----------------------------
true[bool]
true[bool]
default: true[bool]

Type Conversion

Type Cast

package main

import "fmt"

func main() {
	// int → float64
	var i1 int = 1
	var f1 float64 = float64(i1)
	// i1: 1(int) f1: 1(float64)
	fmt.Printf("i1: %v(%T) f1: %v(%T)\n", i1, i1, f1, f1)

	// float64 → int
	var f2 float64 = 1.11111
	var i2 int = int(f2)
	// i2: 1(int) f2: 1.11111(float64)
	fmt.Printf("i2: %v(%T) f2: %v(%T)\n", i2, i2, f2, f2)
}

Type Cast(Pointer)

Casts MyInt to int.

package main

import "fmt"

func main() {
	type MyInt int
	i1 := MyInt(1)

	var i2 *int
	i2 = (*int)(&i1)
	fmt.Printf("i1: %v(%T) &i1: %v(%T)\n", i1, i1, &i1, &i1)
	fmt.Printf("i2: %v(%T) *i2: %v(%T)\n", i2, i2, *i2, *i2)

	*i2 = 100
	fmt.Printf("i1: %v(%T) &i1: %v(%T)\n", i1, i1, &i1, &i1)
	fmt.Printf("i2: %v(%T) *i2: %v(%T)\n", i2, i2, *i2, *i2)
}
i1: 1(main.MyInt) &i1: 0xc0000160a0(*main.MyInt)
i2: 0xc0000160a0(*int) *i2: 1(int)
i1: 100(main.MyInt) &i1: 0xc0000160a0(*main.MyInt)
i2: 0xc0000160a0(*int) *i2: 100(int)

Since it is a pointer, updating i2 also changes the value of i1.

strconv.Atoi, strconv.ItoA

Convert between string and int using strconv.

package main

import (
	"fmt"
	"strconv"
)

func main() {
	// string → int
	s1 := "999"
	i1, _ := strconv.Atoi(s1)
	// s1: 999(string) i1: 999(int)
	fmt.Printf("s1: %v(%T) i1: %v(%T)\n", s1, s1, i1, i1)

	// int → string
	i2 := 999
	s2 := strconv.Itoa(i2)
	// s2: 999(string) i2: 999(int)
	fmt.Printf("s2: %v(%T) i2: %v(%T)\n", s2, s2, i2, i2)
}

Reference

Let's share this post !
TOC