设为首页 收藏本站
查看: 1092|回复: 0

[经验分享] Golang入门教程(九)复合数据类型使用案例二

[复制链接]

尚未签到

发表于 2018-9-20 13:12:00 | 显示全部楼层 |阅读模式
  参考:http://www.runoob.com/go/go-slice.html

目录


  • 切片
  • 字典(map)
  • 函数(func)
  • 接口(interface)
  • 通道(chan)
四、切片(Slice)
  Go 语言切片是对数组的抽象。
  Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。
  声明一个未指定大小的数组来定义切片:
  

var>  

  带有 T 类型元素的切片由 []T 表示,其中T代表slice中元素的类型。切片在内部可由一个结构体类型表示,形式如下:
  

type slice struct {  Length  int
  Capacity  int
  ZerothElement *byte
  
}
  

  

  可见一个slice由三个部分构成:指针、长度和容量。指针指向第一个slice元素对应的底层数组元素的地址。长度对应slice中元素的数目;长度不能超过容量,容量一般是从slice的开始位置到底层数据的结尾位置。通过len和cap函数分别返回slice的长度和容量。
  切片和数组的区别


  • 数组声明需要指定元素类型及元素个数 (数组长度必须是整数且大于 0),语法格式:var variable_name [SIZE] variable_type
  • 声明一个未指定大小的数组来定义切片(切片不需要说明长度),语法格式:var identifier []type
  • 切片不是数组,但是切片底层指向数组
  • 切片本身长度是不一定的因此不可以比较,数组是可以的
  • 切片是变长数组的替代方案,可以关联到指向的底层数组的局部或者全部
  • 切片是引用传递(传递指针地址),而数组是值传递(拷贝值)
  • 切片可以直接创建,引用其他切片或数组创建
  • 如果多个切片指向相同的底层数组,其中一个值的修改会影响所有的切片
  Demo 代码
  

package main  

  
import "fmt"
  

  
func main() {
  //def & init 1
  s1 := []float32{1.2, 1.3, 4.0, 7, 10}
  fmt.Println("s1 = ", s1)
  

  //def & init 2
  s2 := s1[2:4]
  fmt.Println("s2 = ", s2)
  

  //def & init 3
  s3 := s1[:4]
  fmt.Println("s3 = ", s3)
  
}
  

  执行结果
DSC0000.png

  demo2
  

package main  

  
import "fmt"
  

  
func main() {
  

  /* [1] 初始化数组,初始化数组中 {} 中的元素个数不能大于 [] 中的数字*/
  var arr1 = [5]float32{1.2,3.4,5.6,4.4,6.6} //必须指定数组大小
  

  // [2] 如果忽略 [] 中的数字不设置数组大小,Go 语言会根据元素的个数来设置数组的大小
  var arr2 = [...]int{1,3,5,7,9,11}
  

  /* [3] 数组元素可以通过索引(位置)来读取。格式为数组名后加中括号,中括号中为索引的值*/
  fmt.Println("-------打印数组1:",arr1[1])
  fmt.Println("-------打印数组2:",arr2[1])
  fmt.Printf("-------开始切片----------\n")
  

  /* [4] 切片的字面值和数组字面值很像,不过切片没有指定元素个数*/
  slice1 := []float32{1.2,3.4,5.6,4.4,6.6}
  

  /* 使用make函数创建切片 */
  // func make([]T, len, cap) []T : T 代表被创建的切片元素的类型。函数 make 接受一个类型、一个长度和一个可选的容量参数。调用 make 时,内部会分配一个数组,然后返回数组对应的切片。
  slice2 := make([]int,5,10)
  

  // 使用内置函数 len 和 cap 获取切片的长度和容量信息
  fmt.Printf("------获取切片 slice1 的长度和容量信息 len=%d cap=%d slice=%v\n",len(slice1),cap(slice1),slice1)
  fmt.Printf("------获取切片 slice2 的长度和容量信息 len=%d cap=%d slice=%v\n",len(slice2),cap(slice2),slice2)
  

  // 零值的切片类型变量为 nil。对于零值切片变量,len 和 cap 都将返回 0。
  b := []byte{'g', 'o', 'l', 'a', 'n', 'g'} // len=6 cap=6 slice=[103 111 108 97 110 103]
  slice3 := []int{1,2,3,4,5,6,7}
  fmt.Printf("------获取切片 b 的长度和容量信息 len=%d cap=%d slice=%v\n",len(b),cap(b),b)
  fmt.Printf("------获取切片 slice3 的长度和容量信息 len=%d cap=%d slice=%v\n",len(slice3),cap(slice3),slice3)
  
}
  


执行结果
DSC0001.png


切片截取
  

package main  

  
import "fmt"
  

  
func main() {
  /* 创建切片 */
  numbers := []int{0,1,2,3,4,5,6,7,8}
  printSlice(numbers)
  

  /* 打印原始切片 */
  fmt.Println("numbers ==", numbers)
  

  /* 打印子切片从索引1(包含) 到索引4(不包含)*/
  fmt.Println("numbers[1:4] ==", numbers[1:4])
  

  /* 默认下限为 0*/
  fmt.Println("numbers[:3] ==", numbers[:3])
  

  /* 默认上限为 len(s)*/
  fmt.Println("numbers[4:] ==", numbers[4:])
  

  numbers1 := make([]int,0,5)
  printSlice(numbers1)
  

  /* 打印子切片从索引  0(包含) 到索引 2(不包含) */
  number2 := numbers[:2]
  printSlice(number2)
  

  /* 打印子切片从索引 2(包含) 到索引 5(不包含) */
  number3 := numbers[2:5]
  printSlice(number3)
  

  
}
  

  
// 参数为一个切片
  
func printSlice(x []int){
  fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
  
}
  

  

DSC0002.png

  如果想增加切片的容量,我们必须创建一个新的更大的切片并把原分片的内容都拷贝过来。下面的代码描述了从拷贝切片的 copy 方法和向切片追加新元素的 append 方法。
  

package main  

  
import "fmt"
  

  
func main() {
  var numbers []int
  printSlice(numbers)
  

  //允许追加空切片
  numbers = append(numbers, 0)
  printSlice(numbers)
  

  /* 向切片添加一个元素 */
  numbers = append(numbers, 12)
  printSlice(numbers)
  

  /* 同时添加多个元素 */
  numbers = append(numbers, 100, 200, 4000)
  printSlice(numbers)
  

  /* 创建切片 numbers1 是之前切片的两倍容量*/
  numbers1 := make([]int, len(numbers), (cap(numbers))*2)
  

  /* 拷贝 numbers 的内容到 numbers1 */
  copy(numbers1, numbers)
  printSlice(numbers1)
  
}
  

  
// 参数为一个切片
  
func printSlice(x []int) {
  fmt.Printf("len=%d cap=%d slice=%v\n", len(x), cap(x), x)
  
}
  

  

DSC0003.png

  更多了解:Go基础Slice教程详解

五、字典(map)
  Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。
  Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。

定义 Map
  可以使用内建函数 make 也可以使用 map 关键字来定义 Map
  

var map_variable map[key_data_type]value_data_type  

  代码
  

package main  

  
import "fmt"
  

  
func main() {
  

  var map_hostip map[string]string
  map_hostip = make(map[string]string)
  

  map_hostip["host31"] = "192.168.32.131"
  map_hostip["host32"] = "192.168.32.132"
  map_hostip["host33"] = "192.168.32.133"
  map_hostip["host34"] = "192.168.32.134"
  

  fmt.Println("map_hostip = ", map_hostip)
  fmt.Println("map_hostip[host31] = ", map_hostip["host31"])
  

  
}
  

  执行结果
DSC0004.png

  案例2
  

package main  

  
import "fmt"
  

  
func main() {
  

  // [1] 声明map 语法:var map_variable map[key_data_type]value_data_type
  var map1 map[string]string
  

  /* 使用make函数创建一个非nil的map(创建集合),nil map不能赋值 */
  map1 = make(map[string]string)
  

  /* 给已声明的map赋值 */
  map1["name"] = "Tinywan"
  map1["age"] = "24"
  

  /* [2] 直接创建map */
  map2 := make(map[string]string)
  /* 赋值 */
  map2["name"] = "Tinyaiai"
  map2["age"] = "25"
  

  /* [3] 初始化 + 赋值一体化 */
  map3 := map[string]string{
  "name": "ShaoBo Wan",
  "age":  "26",
  }
  

  /* 使用 key 输出 map 值 */
  fmt.Printf("-------遍历 map1---------\n")
  for name := range map1 {
  fmt.Println("map1 of", name, "is", map1[name])
  }
  

  // 遍历 map2
  fmt.Printf("-------遍历 map2---------\n")
  for k, v := range map2 {
  fmt.Println(k, v)
  }
  

  // 遍历 map3
  fmt.Printf("-------遍历 map3---------\n")
  for k, v := range map3 {
  fmt.Println(k, v)
  }
  

  // 查找键值是否存在
  fmt.Printf("-------查找键值是否存在---------\n")
  if v, ok := map1["name"]; ok {
  fmt.Println("存在", v)
  } else {
  fmt.Println("Key Not Found")
  }
  

  /* 删除元素 */
  delete(map3, "age")
  fmt.Printf("--------删除后的 map3--------\n")
  

  // 遍历 map3
  for k, v := range map3 {
  fmt.Println(k, v)
  }
  
}
  

  执行结果
DSC0005.png


六、函数(func)和接口(interface)
  Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。
  代码
  

package main  

  
import "fmt"
  

  
// 定义结构体
  
type person struct {
  id      int
  name    string
  country string
  
}
  

  
// 定义接口
  
type interface_person interface {
  introduction()
  
}
  

  
//实现接口方法 使用指针访问
  
func (this *person) introduction() {
  fmt.Println("My name is : ", this.name)
  
}
  

  
func main() {
  

  var Tinywan person
  Tinywan.id = 13669361192
  Tinywan.name = "ShaoBo Wan"
  Tinywan.country = "China"
  

  fmt.Println("Tinywan = ", Tinywan)
  

  Tinywan.introduction()
  
}
  

  说明:在上面的例子中,我们定义了一个接口 interface_person,接口里面有一个方法introduction()。然后我们在main函数里面定义了一个Tinywan类型变量,并分别为之赋值。然后调用introduction()方法
  执行结果:
DSC0006.png


接口
  Interface类型可以定义一组方法,但是这些不需要实现。并且interface不能包含任何变量。
  interface类型默认是一个指针。
  Interface定义:
  

type Car interface {  NameGet() string
  Run(n int)
  Stop()
  }
  

  

  Interface实现:
  Golang中的接口,不需要显示的实现。只要一个变量,含有接口类型中的所有方法,那么这个变量就实现这个接口。因此,golang中没有implement类似的关键字;
  如果一个变量含有了多个interface类型的方法,那么这个变量就实现了多个接口;如果一个变量只含有了1个interface的方部分方法,那么这个变量没有实现这个接口。
  多态
  一种事物的多种形态,都可以按照统一的接口进行操作。
  

package main  

  
import "fmt"
  

  
// 定义Car 接口
  
type Car interface {
  NameGet() string
  Run(n int)
  Stop()
  
}
  

  
// 宝马结构体
  
type BMW struct {
  Name string
  
}
  

  
// 实现方法
  
func (this *BMW) NameGet() string {
  return this.Name
  
}
  

  
func (this *BMW) Run(n int) {
  fmt.Printf("BMW is running of num is %d \n", n)
  
}
  

  
func (this *BMW) Stop() {
  fmt.Printf("BMW is stop \n")
  
}
  

  
// 大奔 结构体
  
type Benz struct {
  Name string
  
}
  

  
func (this *Benz) NameGet() string {
  return this.Name
  
}
  

  
func (this *Benz) Run(n int) {
  fmt.Printf("Benz is running of num is %d \n", n)
  
}
  

  
func (this *Benz) Stop() {
  fmt.Printf("Benz is stop \n")
  
}
  

  
func (this *Benz) ChatUp() {
  fmt.Printf("ChatUp \n")
  
}
  

  
func main() {
  var car Car /* 声明 car 为 Car 类型 */
  fmt.Println(" car is = ", car)
  fmt.Println("-----------------------\r\n")
  

  var bmw BMW = BMW{Name: "宝马"}
  car = &bmw
  fmt.Println(car.NameGet()) //宝马
  car.Run(1)                 // BMW is running of num is 1
  car.Stop()                 // BMW is stop
  fmt.Println("-----------------------\r\n")
  

  benz := &Benz{Name: "大奔"}
  car = benz
  fmt.Println(car.NameGet()) //大奔
  car.Run(2)                 //Benz is running of num is 2
  car.Stop()                 //Benz is stop
  
}
  

  

DSC0007.png

  参考:浅谈Go语言中的结构体struct & 接口Interface & 反射

六、通道(chan)
  参考:http://blog.csdn.net/u013870094/article/details/74276726
  通道是go所特有的数据类型之一,详细地使用方法需要结合通道的长度/容量/单向或双向等才能更好地理解的这样一种通信手段。
  声明一个通道很简单,我们使用 chan 关键字即可,除此之外,还要指定通道中发送和接收数据的类型,这样我们才能知道,要发送什么类型的数据给通道,也知道从这个通道里可以接收到什么类型的数据。
  

ch:=make(chan int)  

  通道类型和Map这些类型一样,可以使用内置的 make 函数声明初始化,这里我们初始化了一个 chan int 类型的通道,所以我们只能往这个通道里发送 int 类型的数据,当然接收也只能是 int 类型的数据。
  代码
  

package main  

  
import "fmt"
  

  
func main() {
  fmt.Println("function begins ... ")
  c := make(chan bool)
  go func() {
  fmt.Println("func has been called.")
  close(c)
  }()
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-598903-1-1.html 上篇帖子: Golang学习笔记:goroutine 下篇帖子: Golang cpu的使用设置
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表