zoukankan      html  css  js  c++  java
  • Google资深工程师深度讲解Go语言内建容器(三)

    一数组

    1. 数量写在类型前面
    2. 可通过_省略变量
    3. 不仅range,任何地方都可通过_省略变量
    4. 如果只要i下标,可写成 for i:= range numbers
      package main
      
      import "fmt"
      
      func main() {
      	//定义数组的方法
      	var arr1 [5]int
      	arr2 := [3]int{1, 3, 5}
      	arr3 := [...]int{2, 4, 6, 8, 10}
      	var grid [4][5]int
      
      	fmt.Println(arr1, arr2, arr3) //[0 0 0 0 0] [1 3 5] [2 4 6 8 10]
      	fmt.Println(grid)             //4行5列 [[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]
      
      	//遍历:方法一
      	/*for i:=0; i<len(arr3);i++  {
      		fmt.Println(arr3[i])
      		//2
      		//4
      		//6
      		//8
      		//10
      	}*/
      
      	//方法二
      	//下标和键值都要
      	for i,v:=range arr3 {
      		fmt.Println(i,v)
      	}
      	//0 2
      	//1 4
      	//2 6
      	//3 8
      	//4 10
      
      	//只要键值
      	for _,v:=range arr3 {
      		fmt.Println(v)
      	}
      	//2
      	//4
      	//6
      	//8
      	//10
      
      	//只要下标
      	for i := range arr3 {
      		fmt.Println(i)
      	}
      	//0
      	//1
      	//2
      	//3
      	//4
      }
      

      为什么要用range?   

    •   意义明确美观
    •    c++ 没有类似能力
    • Java/Python:只能for each value,不能同时获取i,v

    数组是值类型

    • int[10] 和int[20] 是不同类型
    • 调用func f(arr [10]int)会拷贝数组
    • 在go语言中一般不直接使用数组
      package main
      
      import "fmt"
      
      func printArray(arr *[5]int) {
      	arr[0] = 100
      	for i, v := range arr {
      		fmt.Println(i, v)
      	}
      }
      
      func main() {
      	//定义数组的方法
      	var arr1 [5]int
      	arr2 := [3]int{1, 3, 5}
      	arr3 := [...]int{2, 4, 6, 8, 10}
      	var grid [4][5]int
      
      	fmt.Println(arr1, arr2, arr3) //[0 0 0 0 0] [1 3 5] [2 4 6 8 10]
      	fmt.Println(grid)             //4行5列 [[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]
      
      	//遍历:方法一
      	/*for i:=0; i<len(arr3);i++  {
      		fmt.Println(arr3[i])
      		//2
      		//4
      		//6
      		//8
      		//10
      	}*/
      
      	//方法二
      	//下标和键值都要
      	/*for i,v:=range arr3 {
      		fmt.Println(i,v)
      	}*/
      	//0 2
      	//1 4
      	//2 6
      	//3 8
      	//4 10
      
      	//只要键值
      	/*for _,v:=range arr3 {
      		fmt.Println(v)
      	}*/
      	//2
      	//4
      	//6
      	//8
      	//10
      
      	//只要下标
      	/*for i := range arr3 {
      		fmt.Println(i)
      	}*/
      	//0
      	//1
      	//2
      	//3
      	//4
      	//数组是值类型
      	fmt.Println("arr1")
      	printArray(&arr1)
      
      	fmt.Println("arr3")
      	printArray(&arr3)//取地址后
      
      	fmt.Println("arr1 and arr3")
      	fmt.Println(arr1, arr3) //取指针后  [100 0 0 0 0] [100 4 6 8 10]
      
      	//printArray(arr2)
      
      }
      

    二. slice 切片:

    s:=[2:6] 半开半闭区间 ,s的值为[2,3,4,5]

    package main
    
    import "fmt"
    
    func main() {
    	arr := [...]int{0,1, 2, 3, 4, 5, 6}
    	s := arr[2:6]
    	fmt.Println("arr[2:6]", s) //切片半开半闭区间 arr[2:6] [2 3 4 5]
    }
    

    package main
    
    import "fmt"
    
    func updateSlice(s []int) {
    	s[0] = 100
    }
    
    func main() {
    	arr := [...]int{0, 1, 2, 3, 4, 5, 6,7}
    	//s := arr[2:6]
    	//fmt.Println("arr[2:6]", s) //切片半开半闭区间 arr[2:6] [2 3 4 5]
    	fmt.Println("arr[2:6]", arr[2:6]) // arr[开始下标:结束下标]
    	fmt.Println("arr[:6]", arr[:6])
    	s1 := arr[2:]
    	fmt.Println("s1", arr[2:])
    	s2 := arr[:]
    	fmt.Println("s2", arr[:])
    
    	fmt.Println("after update slice(s1)")
    	updateSlice(s1)
    	fmt.Println(s1)
    	fmt.Println(arr)
    	//after update slice
    	//[100 33 4 5 6]
    	//[0 1 100 33 4 5 6]
    
    	fmt.Println("after update slice(s2)")
    	updateSlice(s2)
    	fmt.Println(s2)
    	fmt.Println(arr)
    	//after update slice(s2)
    	//[100 1 100 33 4 5 6]
    	//[100 1 100 33 4 5 6]
    	fmt.Println("extending slice")
    	arr[0],arr[2]=0,2
    	s1=arr[2:6]
    	s2=s1[3:5]
    	fmt.Println("arr:",arr)//arr= [0 1 2 3 4 5 6 7]
    	fmt.Println("s1:",s1)
    	fmt.Println("s2:",s2)
    	fmt.Println("--")
    	fmt.Println("arr=",arr)
    	fmt.Println("s1=%v,len(s1)=%d,cap(s1)=%d",s1,len(s1),cap(s1))//s1=%v,len(s1)=%d,cap(s1)=%d [2 3 4 5] 4 6
    	fmt.Println("s2=%v,len(s2)=%d,cap(s2)=%d",s2,len(s2),cap(s2))//s2=%v,len(s2)=%d,cap(s2)=%d [5 6] 2 3
    	fmt.Println(s1[3:6])// [5 6 7]
    }
    
    //arr[2:6] [2 33 4 5]
    //arr[:6] [0 1 2 33 4 5]
    //arr[2:] [2 33 4 5 6]
    //arr[:] [0 1 2 33 4 5 6]
    

    操作:

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

    由于值传递的关系,必须接受append的返回值

    package main
    
    import "fmt"
    
    func printSlice(s []int) {
    	fmt.Printf("%v,len=%d,cap=%d \n", s, len(s), cap(s))
    }
    func main() {
    	fmt.Println("Create slice")
    	var s []int
    	for i := 0; i < 100; i++ {
    		printSlice(s)
    		s = append(s, 2*i+1)
    	}
    	fmt.Println(s)
    	fmt.Println(len(s))//100
    
    	s1 := []int{2, 4, 6, 8} [2 4 6 8],len=4,cap=4 
    	s2 := make([]int, 16)//[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0],len=16,cap=16 
    	s3 := make([]int, 10, 32)//[0 0 0 0 0 0 0 0 0 0],len=10,cap=32 
    	printSlice(s1)
    	printSlice(s2)
    	printSlice(s3)
    
    	fmt.Println("copy slice")
    	copy(s2, s1)
    	printSlice(s2)
    	//copy slice
    	//[2 4 6 8 0 0 0 0 0 0 0 0 0 0 0 0],len=16,cap=16
    	
    	fmt.Println("delete elements from slice")
    	s2 = append(s2[:3], s2[4:]...)
    	printSlice(s2)
    	//delete elements from slice
    	//[2 4 6 0 0 0 0 0 0 0 0 0 0 0 0],len=15,cap=16 
    	
    	
    	fmt.Println("popping  from  front")
    	front := s2[0]
    	s2 = s2[1:]
    	fmt.Println(front)
    	printSlice(s2)
    	//popping  from  front
    	//2
    	//[4 6 0 0 0 0 0 0 0 0 0 0 0 0],len=14,cap=15 
    	
    	fmt.Println("popping  from back")
    	tail := s2[len(s2)-1]
    	s2 = s2[:len(s2)-1]
    	fmt.Println(tail)
    	printSlice(s2)
    	//popping  from back
    	//0
    	//[4 6 0 0 0 0 0 0 0 0 0 0 0],len=13,cap=15 
    }
    

    三.map

       1.map的操作

    • 创建:make(map[string]int)
    • 获取元素:m[key]
    • key不存在时,获得value类型的初始值
    • 用value,ok:=m[key]来判断是否存在key
    • 用delete删除一个key

    2.map的遍历

    • 使用range 遍历key,或者遍历key,value对
    • 不保证遍历顺序,如需顺序,需手动对key排序(借助slice)
    • 使用len获得元素个数

    3.map的key

    • map使用哈希表,必须可以比较相等
    • 除了slice,map,function的内建类型都可以作为key
    • struct 类型不包含上述字段,也可作为key
    package main
    
    import "fmt"
    
    func main() {
    	//定义map3种方式
    	m := map[string]string{
    		"name":    "lxw",
    		"course":  "golang",
    		"site":    "imooc",
    		"quality": "notbad",
    	}
    	m2 := make(map[string]int) //m2==empty map
    
    	var m3 map[string]int //m3==nil
    
    	fmt.Println(m, m2, m3)
    	fmt.Println("==traversing map==")
    	for k, v := range m {
    		fmt.Println(k, v)
    	}
    
    	fmt.Println("---getting values---")
    	courseName, ok := m["course"]
    	fmt.Println(courseName, ok)
    
    	//判断键是否存在
    	if casseName, ok2 := m["caurse"]; ok2 {
    		fmt.Println(casseName)
    	} else {
    		fmt.Println("key does not exist")
    	}
    
    	fmt.Println("--deleting values---")
    	courseName, ok3 := m["name"]
    	fmt.Println(courseName, ok3)
    
    	delete(m, "name")
    	courseName, ok3 = m["name"]
    	fmt.Println(courseName, ok3)
    }
    /*map[course:golang name:lxw quality:notbad site:imooc] map[] map[]
    ==traversing map==
    quality notbad
    name lxw
    course golang
    site imooc
    ---getting values---
    golang true
    key does not exist
    --deleting values---
    lxw true
    false*/
    package main
    
    import "fmt"
    //最长不含有重复字符的子串
    func lenthOfNonRepeatingSubstr(s string) int {
    	lastOccurred := make(map[byte]int)
    	start := 0
    	maxLength := 0
    	for i, ch := range []byte(s) {
    		if lastI, ok := lastOccurred[ch]; ok && lastI >= start {
    			start = lastI + 1
    		}
    		if i-start+1 > maxLength {
    			maxLength = i - start + 1
    		}
    		lastOccurred[ch] = i
    	}
    	return maxLength
    }
    
    func main() {
    	fmt.Println(lenthOfNonRepeatingSubstr("abcabcbb")) //3
    	fmt.Println(lenthOfNonRepeatingSubstr("bbbbb"))    //1
    	fmt.Println(lenthOfNonRepeatingSubstr("pwwkew"))   //3
    }
    

    四.字符串

    • rune 相当于go的char;每个中文3个字节;
    • 使用range遍历pos,rune对
    • 使用utf8.RuneCountInString获得字符数量
    • 使用len获得字节长度
    • 使用[]byte获得字节

    其他字符串操作

    • Fileds,split,join
    • Contains,Index
    • Tolower,toupper
    • Trim,trimRight,trimLeft
      //最长不含有重复字符的子串(国际版中英文都可以)
      package main
      
      import "fmt"
      //最长不含有重复字符的子串
      func lenthOfNonRepeatingSubstr(s string) int {
      	lastOccurred := make(map[rune]int)
      	start := 0
      	maxLength := 0
      	for i, ch := range []rune(s) {
      		if lastI, ok := lastOccurred[ch]; ok && lastI >= start {
      			start = lastI + 1
      		}
      		if i-start+1 > maxLength {
      			maxLength = i - start + 1
      		}
      		lastOccurred[ch] = i
      	}
      	return maxLength
      }
      
      func main() {
      	fmt.Println(lenthOfNonRepeatingSubstr("abcabcbb")) //3
      	fmt.Println(lenthOfNonRepeatingSubstr("bbbbb"))    //1
      	fmt.Println(lenthOfNonRepeatingSubstr("pwwkew"))   //3
      	fmt.Println(lenthOfNonRepeatingSubstr(""))//0
      	fmt.Println(lenthOfNonRepeatingSubstr("b"))//1
      	fmt.Println(lenthOfNonRepeatingSubstr("abcdef"))//6
      	fmt.Println(lenthOfNonRepeatingSubstr("这里是中国"))//5
      	fmt.Println(lenthOfNonRepeatingSubstr("一二三二一"))//3
      	fmt.Println(lenthOfNonRepeatingSubstr("黑化肥发灰会挥发灰化肥发挥会发黑"))//7
      }
      

    赞赏码

    非学,无以致疑;非问,无以广识

  • 相关阅读:
    动手动脑3
    动手动脑2
    编写一个文件分割工具,能把一个大文件分割成多个小的文件。并且能再次把他们合并起来得到完整的文件
    编写一个文件加解密程序通过命令行完成加解密工作
    编写一个程序指定一个文件夹,能自动计算出其总容量
    Java中常见的异常处理汇总
    覆盖 动手动脑
    课堂代码验证
    如何在静态方法中访问类的实例成员 及查询“你已经创建了多少个对象”
    Java的字段初始化规律
  • 原文地址:https://www.cnblogs.com/lxwphp/p/15452759.html
Copyright © 2011-2022 走看看