数据类型

字符串

字符串是不可变字节序列

字符串默认值" ",不是nil

使用"`"定义不做转义的原始字符串,支持跨行

支持"!=,<,>,=="操作符

package main

import (
	"fmt"
)

func main() {
	s := "ab" +
		"cd"
	fmt.Println(s == "abcd")
	fmt.Println(s > "abc")
}

  

允许索引号访问字节数组,但是不能获取元素地址

for遍历字符串时,分byte rune两种方式

package main

import (
	"fmt"
)

func main() {
	s := "想飞上天"
	for i := 0; i < len(s); i++ { // byte
		fmt.Printf("%d [%c]
", i, s[i])
	}
	for i, c := range s { //返回数组索引号,以及unicode字符
		fmt.Printf("%d [%c]
", i, c)
	}
}

  

rune

func main() {
	s := "yes我爱慕课网!"
	for _, ch := range []rune(s) {
		fmt.Printf("%c", ch)
	}

  

字符串拼接

加法操作拼接字符串时,每次都需要重新分配内存

改进:预分配足够的内存空间

package main

import (
	"fmt"
	"strings"
)

func test() string {
	s := make([]string, 1000) //分配足够的内存
	for i := 0; i < 1000; i++ {
		s[i] = "a"
	}
	return strings.Join(s, "")
}

func main() {
	result := test()
	fmt.Println(result)
}

  

数组

定义数组类型时,长度是类型组成部分,元素类型相同,但长度不同的数组不属于同一类型

数组的初始化方式

package main

import (
	"fmt"
)

func main() {
	var a [4]int //元素自动初始化为零
	b := [4]int{2, 5} //未提供初始化的元素自动初始化为0
	c := [4]int{5, 3: 10} //指定索引位置初始化
	d := [...]int{1, 2, 3} // 编辑器按初始化值数量确定数组长度
	e := [...]int{10, 3: 100} // 支持索引初始化,但注意数组长度与此有关
	fmt.Println(a)
	fmt.Println(b)
	fmt.Println(c)
	fmt.Println(d)
	fmt.Println(e)
}
  • [10] int和[20] int 是不同的数据类型
  • 使用var定义时不需要初始化值,:= 需要写上初始值
  • 数组是值类型,作为参数传入函数中,不会改变初始值;想要改变可以用指针a *[5] int

 通过指针修改数组

func array(a *[5]int) {
	a[0] = 100
	for _, v := range a {
		fmt.Println(v)
	}
}

func main() {
	var a [5]int
	array(&a)
}

  

对于结构复杂的类型,省略元素初始化类型标签

package main

import (
	"fmt"
)

func main() {
	type user struct {
		name string
		age  int
	}

	d := [...]user{
		{"tom", 20},
		{"jack", 22},
	}

	fmt.Println(d)
}

  

在定义多维数组时,仅第一维度允许使用"..."

package main

import (
	"fmt"
)

func main() {
	a := [2][2]int{
		{1, 2},
		{3, 4},
	}
	b := [...][2]int{
		{1, 2},
		{3, 4},
		{5, 6},
	}
	fmt.Println(a)
	fmt.Println(b)
}

  

切片

切片的几种创建方式

	s6 := []int{1, 2, 3} //不指定长度
	s7 := make([]int, 10) //指定长度10
	s8 := make([]int, 10, 30) //长度10,cap30

  

切片取值

func array(a [7]int) {
	s := a[2:6]
	fmt.Println(s)
}

func main() {
	array([...]int{1, 2, 3, 4, 5, 6, 7})
}

左开右闭,输出结果

[3 4 5 6]

  

切片copy,delete

func main() {
	s1 := make([]int, 10, 30) //长度10,cap30
	s2 := []int{2, 4, 6, 8}
	//copy slice
	copy(s1, s2)
	fmt.Println(s1)
	//delete slice
	s3 := append(s1[:3], s1[4:]...)
	fmt.Println(s3)
}

  

输出结果

[2 4 6 8 0 0 0 0 0 0]
[2 4 6 0 0 0 0 0 0]

  

引用传递,修改数组值

func printArray(a []int) {
	a[0] += 100
}

func main() {
	array := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
	printArray(array[:]) //数组转切片 [:]
	fmt.Println(array)
}

输出

[100 1 2 3 4 5 6 7]

反转数组a

package main

import "fmt"

func reverse(s []int) {
	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
		s[i], s[j] = s[j], s[i]
	}
}
func main() {
	a := [...]int{0, 1, 2, 3, 4, 5}
	reverse(a[:])
	fmt.Println(a)
}

  

slice扩展

func main() {
	array := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
	s1 := array[2:6]
	s2 := s1[3:5]
	fmt.Println(s1, s2)
	//slice可以向后扩展,不能向前扩展
	//len切片长度 cap切片容量
     //s[i]不可以超越len(s),向后扩展不可以超越底层数组cap(s) }

  

输出

[2 3 4 5] [5 6]

添加元素时如果超越cap,系统会重新分配更大的底层数组

func main() {
	array := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
	s1 := array[2:6]
	s2 := s1[3:5]
	s3 := append(s2, 10)
	s4 := append(s3, 11)
	s5 := append(s4, 12)
	fmt.Println(s3, s4, s5, array)
}

  

输出

[5 6 10] [5 6 10 11] [5 6 10 11 12] [0 1 2 3 4 5 6 10]

  

指针

指针数组是指元素为指针类型的数组,数组指针是获取数组变量的地址

数组指针可直接用来操作元素

package main

import (
	"fmt"
)

func main() {
	x, y := 10, 20
	a := [...]int{x, y}
	p := &a

	p[1] += 10
	fmt.Println(p[1])
	fmt.Println(p)
}

  

复制

数组是值类型,赋值和传参都会copy数据,可改用指针或切片避免

字典

字典是引用类型,make函数创建

创建

package main

import (
	"fmt"
)

func main() {
	m := make(map[string]int)
	m["a"] = 1
	m["b"] = 2
	m2 := map[int]struct{ x int }{ //值为匿名结构类型
		1: {x: 100},
		2: {x: 200},
	}
	fmt.Println(m)
	fmt.Println(m2)
}

  

package main

import (
	"fmt"
	"sort"
)

func testMap() {
	// var a map[string]string = map[string]string{"abc": "edf"}
	a := make(map[string]string, 10)

	a["abc"] = "edf"
	fmt.Println(a)
}

func testMap2() {
	a := make(map[string]map[string]string, 10)
	a["key"] = make(map[string]string, 10)
	a["key"]["key1"] = "1"
	a["key"]["key2"] = "2"
	fmt.Println(a)
}

func testMapSort() {
	a := make(map[int]int, 5)
	a[8] = 10
	a[1] = 10
	a[4] = 10
	a[5] = 10
	a[2] = 10
	var keys []int

	for k, _ := range a {
		keys = append(keys, k)
	}
	sort.Ints(keys)

	for _, v := range keys {
		fmt.Println(v, a[v])
	}
}

func main() {
	// testMap2()
	testMapSort()
}

  

基本操作

package main

import (
	"fmt"
)

func main() {
	m := map[string]int{
		"a": 1,
		"b": 2,
	}
	m["a"] = 10 //修改
	m["c"] = 30 //新增

	if v, ok := m["d"]; ok { //判断key是否存在,不存在默认返回零值
		println(v)
	}
	delete(m, "c") //删除
	fmt.Println(m)
}

  

对字典进行迭代,每次返回的键值次序不相同

package main

import (
	"fmt"
)

func main() {
	m := make(map[string]int)
	for i := 0; i < 10; i++ {
		m[string('a'+i)] = i
	}

	for i := 0; i < 4; i++ {
		for k, v := range m {
			fmt.Printf("%v:%v	", k, v)
		}
		fmt.Println()
	}
}

  

因内存访问安全和哈希算法等缘故,字典被设计成not addressable,不能直接修改value成员(结构体或数组)

package main

type user struct {
	name string
	age  int
}

func main() {
	m := map[int]user{
		1: {"alex", 20},
	} 
	m[1].age += 1  //error
}

  

正确做法是先返回整个value,修改后重设字典键值 或者通过指针

package main

import (
	"fmt"
)

type user struct {
	name string
	age  int
}

func main() {
	m := map[int]user{
		1: {"alex", 20},
	}
	m2 := map[int]*user{
		1: &user{"jack", 25},
	}
	u := m[1]
	u.age = 18
	m[1] = u
	m2[1].age++ //m2[1]返回的是指针,可透过指针修改目标对象
	fmt.Println(m)
	fmt.Println(*m2[1])
}

  

寻找最长不含有重复字符的子串

思路:对于每一个字母x,lastoccured[x]不存在,或者<start ;无需操作

lastoccured[x]>= start ;更新start

更新lastoccured[x],更新maxlength

func lengthOfLongestSubstring(s string) int {
	lastOccured := make(map[byte]int)
	start := 0
	maxLength := 0

	for i, ch := range []byte(s) {
		if lastI, ok := lastOccured[ch]; ok && lastI >= start {
			start = lastI + 1
		}
		if i-start+1 > maxLength {
			maxLength = i - start + 1
		}
		lastOccured[ch] = i
	}
	return maxLength
}

  

原文地址:https://www.cnblogs.com/hongpeng0209/p/8988363.html