为编程爱好者分享易语言教程源码的资源网
好用的代理IP,游戏必备 ____广告位招租____ 服务器99/年 ____广告位招租____ ____广告位招租____ 挂机,建站服务器
好用的代理IP,游戏必备 ____广告位招租____ 服务器低至38/年 ____广告位招租____ ____广告位招租____ 挂机,建站服务器

网站首页 > 网络编程 > 其它综合 正文

golang 复合数据类型

三叶资源网 2022-10-24 19:18:50 其它综合 271 ℃ 0 评论

数组

固定长度,不如slice灵活,go中很少直接使用数组。

数组是值传递,不能通过修改数组类型的参数来修改这个数组的值。

package main

import "fmt"

func main() {
    x := [3]int{1, 2, 3}

    func(arr [3]int) {
        arr[0] = 7
        fmt.Println(arr)
    }(x)

    fmt.Println(x)
}
[7 2 3]
[1 2 3]
q := [...]int{1,2,3}
如果数组长度位置是省略号,则数组长度由实际插入决定

slice

  • 变长序列。写法是[]T,T代表类型。
  • 前边整理过的s[m:n] s[m:] s[:n] s[:]
  • 跟数组一样,切片包括一个执行第一个值的指针,所以复制是就是生成一个别名的指针,指向第一个值。
  • 切片反转
  • 不能通过== 判断两个切片是否相同,但是可以通过bytes.Equal函数判断两个字节型slice是否相容([]byte),但是对于其他类型的slice必须自己展开比较。
  • 判断为空;
len(s)==0
  • 用内置的make函数创建一个指定元素类型、长度和容量的slice。容量部分可以忽略,容量将等于长度。
make([]T,len)
make([]T,len,cap)   //类似  make([]T,cap)[:len]

这段看不懂 在底层,make创建了一个匿名的数组变量,然后返回一个slice;只有通过返回的slice才能用底层匿名的数组变量。在第一中语言中,slice是整个数组的view。在第二种语句中,slice只引用了底层数组的前len个元素,但是容量包含整个的数组。额外的元素是留给未来的增长用的。

append函数

用于向slice中追加元素

var runes []rune
for _, r:=range "hello, 世界"{
    runes = append(runes, r)
}
fmt.Printf("%q\n", runes)     //"['h' 'e' 'l' 'l' 'o' ',' ' ' '世' '界']"

在循环中使用append构建一个由9个rune字符组成的slice。 - cap()返回的是数组切片分配的空间大小,可以有预留。

my := make([]int, 5, 10)
cap(my)返回的是10,make生成5个初始化值的my切片。
  • copy(a,b)复制切片(有返回值,返回的是成功复制的元素个数),从b复制到a
  • appendInt函数分配时,容量大于切片的容量会重新分配内存,*2。容量够用就不会。
  • append可以追加多个元素甚至可以是一个切片。

slice内存技巧

旋转,反转,修改元素。 - 返回不含空字符串的列表nonempty函数

func nonempty(strings []string) []string {
    i := 0
    for _, s := range strings {
        if s != "" {
            strings[i] = s
            i++
        }
    }
    return strings[:i]
}
  • 一个slice可以模拟一个stack。
stack = append(stack, v)
  • 要删除slice中的某个元素但是保存原有的元素顺序,可以通过内置的copy函数将后边的子slice向前移动一位完成。
func remove(slice []int, i int) []int {
    copy(slice[i:], slice[i+1:])
    return slice[:len(slice)-1]
}
func main() {
    s := []int{5,6,7,8,9}
    fmt.Println(remove(s, 2))   //"[5 6 8 9]"
}
  • 改写reverse函数,用数组指针代替slice
  • 给函数传递数组,传递的只是数组的拷贝,问不是他的指针
package main

import "fmt"

func reverse(s *[5]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() {
    s := [5]int{1,2,3,4,5}
    reverse(&s)
    fmt.Println(s)
}
  • 编写一个rotate函数,通过一次循环完成旋转。
package main

import "fmt"

func rotate(s []int, x int) []int{
    a := make([]int, 5, 10)
    for i := 0; i < len(s); i++ {
        a[i] =  s[(i+x)%5]
    }
    return a
}
func main() {
    my := []int{1,2,3,4,5}
    fmt.Println(rotate(my, 5))
//  fmt.Println(my)
}
  • 消除[]string中相邻重复字符串
func StringNoRep(s []string) []string {
    for i := range s {
        if i == len(s)-1 {
            return s
        }
        if s[i] == s[i+1] {
            s = append(s[:i], s[i+1:]...)
        }
    }
    return s
}

map

在go语言中,一个MAP就是一个哈希表的引用,map类型可以写成map[K]V,key和value。map中所有的key可以使同一类型,所有的value可以是同一类型,但是key和value可以是不同类型。 内置的make函数可以创建一个map:

ages := make(map[string]int)   // mapping from strings to ints
ages["alice"] = 31
ages["chalie"] = 34

ager := map[string]int{
    "alice": 31,
    "charlie": 34
}
  • 内置delete函数可以删除元素。
delete(ages, "alice")
  • 因为map中的元素不是变量,所以不能进行取址操作。
  • 可以用range风格的for循环遍历map的key/value
  • map的迭代顺序是随机的,并且不同的哈希函数实现可能导致不同的遍历顺序。如果要按顺序遍历key/value对,必须显式地对key进行排序,可以使sort包的Strings函数符字符串slice进行排序。
for name, age := range ages{
    fmt.Pringf("%s\t%d\n", name, age)
}
  • 不能向一个nil的map中存数据,在向map中存数据前必须先创建map
  • 使用range遍历map数据类型时,两个变量分别对应map的第一个类型和第二个类型
package main

import "fmt"

func main()  {
    ages := make(map[string]int)   // mapping from strings to ints
    ages["alice"] = 31
    ages["chalie"] = 34
    for i,j := range ages {
        fmt.Println(i)
        fmt.Println(j)
    }
}
alice
31
chalie
34
Process finished with exit code 0

结构体

类似于类中的结构体,需要绑定到一个对象中。利用对象进行访问、复制、取址等工作。 - 参数顺序不同也是不同的结构体。

type Employee struct {
    ID        int
    Name      string
    Address   string
    DoB       time.Time
    Position  string
    Salary    int
    ManagerID int
}

var dilbert Employee

对成员取址,然后通过指针访问

position := &dilbert.Salary
*position = "Senior " + *position // promoted, for outsourcing to Elbonia
  • S结构体中的成员不能是S类型的,但是可以是*S指针类型的,这样可以创建递归的数据结构,如链表和树结构。下边的代码是用数实现插入。
package main

import "fmt"

type tree struct {
    value       int
    left, right *tree
}//每个树的节点都是这个结构体递归出来的。
// Sort sorts values in place.
func Sort(values []int) {
    var root *tree
    for _, v := range values {
        root = add(root, v)
    }
    appendValues(values[:0], root)
}
// appendValues appends the elements of t to values in order
// and returns the resulting slice.
func appendValues(values []int, t *tree) []int {
    if t != nil {
        values = appendValues(values, t.left)
        values = append(values, t.value)
        values = appendValues(values, t.right)
    }
    return values
}

func add(t *tree, value int) *tree {
    if t == nil {
        // Equivalent to return &tree{value: value}.
        t = new(tree)
        t.value = value
        return t
    }
    if value < t.value {
        t.left = add(t.left, value)
    } else {
        t.right = add(t.right, value)
    }
    return t
}
func main() {
    my := []int{1,2,5,8,4,2,5,8}
    Sort(my)
    fmt.Println(my)
}

结构体面值

结构体值也可以用结构体面值表示,可以指定每个成员的值

type Point struct{x,y int}
p := Point{1, 2}

通常用第二种写法,顺序和其他成员的值不用考虑

p := Point{X: 1}

结构体可以做参数和返回值,可以对结构体中的成员做缩放等处理。 因为函数的参数都是值拷贝,所以要对结构体进行修改就要传入指针。

如果结构体的所有成员都是可比较的,那么这个结构体也是可比较的。可比较的结构体类型可以用于map的key类型。

结构体嵌入和匿名成员

两个有相似之处的结构体可以嵌入 比如轮胎和圆和点

type Point struct {
    X, Y int
}

type Circle struct {
    Center Point
    Radius int
}

type Wheel struct {
    Circle Circle
    Spokes int
}

但是访问会很繁琐比如 var w Wheel w.Circle.Center.X = 8 所以要有匿名成员

type Circle struct {
    Point
    Radius int
}

type Wheel struct {
    Circle
    Spokes int
}

各有一个匿名成员。特性是:类型必须是命名的类型或者是指向一个命名的类型的指针。 Point类型嵌入到了Circle结构体,Circle类型嵌入到了Wheel结构体 这样访问就变成了 var w Wheel x.X = 8 这样它们的字面值并没有简短的表示匿名成员的语法,一下语法不存在。

w = Wheel{8, 8, 5, 20}                       // compile error: unknown fields
w = Wheel{X: 8, Y: 8, Radius: 5, Spokes: 20} // compile error: unknown fields

可以用这样的语法

w = Wheel{Circle{Point{8, 8}, 5}, 20}
w.X = 5
fmt.Printf("%#v\n", w)

副词,代表打印时和go语言一样的语法结构

JSON

JSON是对JavaScript中各种类型的值——字符串、数字、布尔值和对象——Unicode文本编码。它可以用有效可读的方式表示第三章的基础数据类型和本章的数组、slice、结构体和map等聚合数据类型。 将GO中的一个结构体的切片转换成JSON的过程叫做编组,通过json.Marsha完成。生成的是很长的字符串,没缩进很难阅读。另一个json.Marshallndent函数是格式化的输出。

data, err := json.MarshalIndent(movies, "", "    ")
if err != nil {
    log.Fatalf("JSON marshaling failed: %s", err)
}
fmt.Printf("%s\n", data)



来源:三叶资源网,欢迎分享,公众号:iisanye,(三叶资源网⑤群:21414575

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

百度站内搜索
关注微信公众号
三叶资源网⑤群:三叶资源网⑤群

网站分类
随机tag
HP-socket3QQ看点评论图形控件采集源码API读写内存支付收款语音素材腾讯滑块验证码模块源码觅风易语言教程加群链接GDI+小程序动态加密QQ看点评论点赞s5代理集群Shell外壳编程会员签到keepDLL函数查看手势验证码百度推广引流软件
最新评论