Loading

切片类型、map、字符串、指针、结构体、方法、

一、切片类型

切片类型:是由数组建立的一种方便灵活的且功能强大的包装,切片本身不拥有任何数据类型,他只是对现有数组的引用。

即:指向了一个地址,本身不拥有数据。

package main

import "fmt"

func main() {
    //切片定义的第一种方式,由数组切出来
    //var a [8]int=[8]int{1,2,3,4,5,6,7,8}
    ////只是对数组的引用
    //var b []int=a[2:6]
    //fmt.Println(b)
    //a[2]=30
    //fmt.Println(b)
    //b[1]=40
    //fmt.Println(b)
    //fmt.Println(a)
    ////原数组的修改会影响切片
    ////切片的修改也会影响底层数组
    //a[1]=20
    //fmt.Println(b)
    //更多用法,没有步长
    //var a [8]int=[8]int{1,2,3,4,5,6,7,8}
    //b:=a[:4]
    //fmt.Println(b)
    //第二种方式,直接定义
    //切片空值是?nil类型
    //var a []int
    //if a==nil{
    //    fmt.Println("我是空的")
    //}
    //a[0]=10
    //fmt.Println(a)
    //定义并初始化,第一个参数是类型,第二个参数是切片的长度,第三个参数是底层数组长度,也就是切片的容量
    //var a []int=make([]int,3)
    //fmt.Println(a)
    //切片的长度和容量(len     cap:容量)
    //切片的长度就是它所包含的元素个数。
    //切片的容量是从它的第一个元素开始数,到其底层数组元素末尾的个数。
    //var a [8]int=[8]int{1,2,3,4,5,6,7,8}
    //var b []int=a[2:6]
    //fmt.Println(len(b))
    //fmt.Println(cap(b))
    //var a []int=make([]int,3,4)
    //fmt.Println(a)
    //fmt.Println(len(a))
    //fmt.Println(cap(a))

    //切片追加值(即给切片赋值)
    //var a [8]int=[8]int{1,2,3,4,5,6,7,8}
    //var b []int=a[2:6]
    //fmt.Println(len(b))  //4
    //fmt.Println(cap(b))  //6
    ////内置函数append,append函数的返回值也为切片
    //b=append(b,555)
    //b=append(b,666)
    //追加两个值之后,容量为6,长度为6
    //底层数组a的相应位置数据也被修改了
    //fmt.Println(b)
    //fmt.Println(len(b))
    //fmt.Println(cap(b))
    //b[0]=999
    //fmt.Println(a)  //a[2]变为999
    //容量满了再继续追加
    //b=append(b,777)
    //fmt.Println(b)
    //长度为7
    //fmt.Println(len(b))
    //切片容量翻倍为12
    //fmt.Println(cap(b))
    //当切片超出底层数组长度时,再进行追加会重新创建一个数组,修改切片中的值不会影响原数组中的值
    //b[0]=999
    //fmt.Println(b)
    //fmt.Println(a)
    //var b =make([]int,3,4)
    //fmt.Println(b)  //[0,0,0]
    //b=append(b,4)
    //fmt.Println(b)  //[0,0,0,4]
    //fmt.Println(len(b))  //4
    //fmt.Println(cap(b))  //4
    //b=append(b,5)
    //fmt.Println(len(b))  //5
    //fmt.Println(cap(b))  //8
    //切片的修改
    //var b =make([]int,3,4)
    //b[0]=999
    //fmt.Println(b)
    //var b =make([]int,4,4)
    //fmt.Println(len(b))
    //fmt.Println(cap(b))
    //切片的函数传递
    //var b =make([]int,3,4)
    //test(b)
    //在函数中修改之后原b切片的值也会改变,即切片是引用传递
    //fmt.Println(b)
    //切片的数据结构表示
    //type slice struct {
    //    Length        int
    //    Capacity      int
    //    ZerothElement *byte
    //}
    //多维切片
    //var a [][]string=make([][]string,2,3)
    //fmt.Println(a[0])  //[]为空切片,只初始化了外层切片
    //a[0]=make([]string,2,3)  //为内层切片初始化
    //if a[0]==nil{
    //    fmt.Println("xxxx")
    //}
    //切片初始化的方法
    //var a []int=[]int{1,2,3}
    //fmt.Println(a)
    //fmt.Println(len(a))
    //fmt.Println(cap(a))
    //多维切片初始化
    //var a [][]string=[][]string{{"1","2"},{"3","4"}}
    //fmt.Println(a)
    //fmt.Println(len(a))
    //fmt.Println(cap(a))
    //a[0][1]="999"
    //fmt.Println(a)
    //a[1][0]="999"
    //var a []int=[]int{1,2}
    //fmt.Println(a)
    //a=append(a,3)
    //fmt.Println(len(a))
    //fmt.Println(cap(a))
    //a[2]=99
    //a[3]=888
    //fmt.Println(a)
    //copy函数
    var a =make([]int,3,10000)
    //底层数组很大,耗费内存
    a[1]=99
    a[2]=888
    fmt.Println(a)

    //var b =make([]int,4,4)
    var b =make([]int,2,4)
    fmt.Println(b)
    //将a copy 到另一个切片上去
    copy(b,a)
    fmt.Println(b)
}

func test(b []int)  {
    b[0]=999
    fmt.Println(b)
}
切片

可变长参数:

package main
//可变长参数
import "fmt"

//可变长参数

func main() {
    //var a =[]int{1,2,4,}
    //test1(1,2,3,4)
    //相当于打散了
    //test1(a...)
    //veggies := []string{"potatoes", "tomatoes", "brinjal"}
    //fruits := []string{"oranges", "apples"}
    //food := append(veggies, fruits...)
    //fmt.Println("food:",food)

    //循环多维切片
    pls := [][]string {
        {"C", "C++"},
        {"JavaScript"},
        {"Go", "Rust"},
    }
    fmt.Println(pls)
    for _,v:=range pls {
        for _,v1:=range v{
            fmt.Println(v1)
        }
    }

}

func test1(a ...int)  {
    fmt.Println(a)
    fmt.Printf("%T",a)

}
可变长参数

二、map

map:在Go中将键(key)值(value)关联起来的内置类型,通过相应的键来获取相应的值。

map中放函数和用map实现set练习:

package main

//回顾

//func main() {

    //指针数组和数组指针
    //数组里面放指针   指向数组的指针
    //

    //a:=10
    //b:=20
    ////数组里面放指针
    //c:=[2]*int{&a,&b}
    //fmt.Println(c)
    //指向数组的指针
    //a:=[2]int{1,2}
    //var b *[2]int
    //b=&a
    //fmt.Println(b)
//}

//-map内放函数
//func main() {
//    var m map[int]func(a int)int=make(map[int]func(a int)int)
//    m[1]= func(a int) int {
//
//        return a
//    }
//    m[2]= func(a int) int {
//        return a*a
//    }
//    m[3]= func(a int) int {
//        return a*a*a
//    }
//
//    fmt.Println(m[1](9))
//    fmt.Println(m[2](9))
//    fmt.Println(m[3](9))
//}

//-通过map实现set
func main() {
    //集合
    //可以放值,如果重复了,放不进去
    //可以获取长度
    //判断一个值是否在集合内
    //把集合内所有元素打印出来
    //
    //var m map[string]bool=make(map[string]bool)
    //m["lqz"]=true
    //m["egon"]=true
    //
    //m["lqz"]=true
    //
    //fmt.Println(len(m))
    ////"aa"是否在集合内
    //if m["aa"]{
    //    fmt.Println("在里面")
    //}else {
    //    fmt.Println("不再")
    //}
    //for k,_:=range m{
    //    fmt.Println(k)
    //}


}
练习
//maps
package main

import "fmt"

func main() {
    //maps的定义
    //map的key值必须可hash

    //var a map[键值类型]value值类型
    //map的空值是nil类型
    //也是引用类型,在函数中修改原来的值也会被修改
    //var a map[int]string
    //fmt.Println(a)
    //if a==nil{
    //    fmt.Println("xxxx")
    //}
    //map的赋值跟取值
    //map的初始化
    //var a map[int]string=make(map[int]string)
    //fmt.Println(a)
    ////if a==nil{
    ////    fmt.Println("xxxxx")
    ////}
    //a[1]="100"
    //a[2]="888"
    //fmt.Println(a)
    //fmt.Println(a[1])
    ////取一个不存在的key值会?返回value值的空值的默认值(int为0,string为“”)
    ////fmt.Println(a[9])
    //var b map[int]int=make(map[int]int)
    //b[1]=100
    //fmt.Println(b)
    ////fmt.Println(b[9])
    //if v,ok:=a[9];ok{
    //    fmt.Println("=-====",v)
    //}else {
    //    fmt.Println("该值不存在")
    //}
    //v,ok:=a[1]
    //fmt.Println(v)
    //fmt.Println(ok)
    //定义和初始化的第二种方式
    //var a =map[int]string{1:"10",2:"100"}
    ////a[1]
    //fmt.Println(a[1])
    //字典删除元素,内置函数
    //var a =map[int]string{1:"10",2:"100"}
    ////delete(a,2)
    //delete(a,3)
    //fmt.Println(a)

    //map长度
    //var a =map[int]string{1:"10",2:"100"}
    //delete(a,1)
    //a[10]="999"
    //fmt.Println(len(a))
    //Map 是引用类型

    //var a =map[int]string{1:"10",2:"100"}
    //test4(a)
    //fmt.Println(a)
    //Map 的相等性

    //map1 := map[string]int{
    //    "one": 1,
    //    "two": 2,
    //}
    //
    //map2 := map1

    //if map1 == map2 {  //报错
    //}

    //map循环出所有元素
    ////map是无序的
    //for k,v:=range a{
    //    fmt.Println(k)
    //    fmt.Println(v)
    //}



    //补充:切片删除元素
    //var a =[]int{1,2,3,4,5,6}
    //a=append(a[0:2],a[3:]...)
    //fmt.Println(a)

}

func test4(a map[int]string)  {
    a[1]="888"
    fmt.Println(a)

}

//把map做成有序作业
map

三、字符串

字符串:

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {

    //name := "Hello World刘清政"
    //name:=""
    //字符串长度,len统计字节数
    //在go中string类型都是utf-8编码
    //fmt.Println(len(name))
    //fmt.Println(utf8.RuneCountInString(name))
    //unicode是一个字符编码对照表
    //循环
    //字符串是个只读切片
    //name := "name刘"
    //循环的是字节
    //for i:=0;i<len(name);i++{
    //    fmt.Println(string(name[i]))
    //    fmt.Printf("%T",name[i])
    //    fmt.Println()
    //}

    //循环的是字符
    //for _,v:=range name{
    //    fmt.Println(string(v))
    //    fmt.Printf("%T",v)
    //    fmt.Println()
    //}

    //name := "name刘"
    //name[0]=99
    //fmt.Println(name[0])
    //fmt.Println(string(name[0]))

    byteSlice := []byte{0x43, 0x61, 0x66, 0xC3, 0xA9}
    str := string(byteSlice)
    a:=len(str)
    b:=utf8.RuneCountInString(str)
    fmt.Println(b)
    fmt.Println(a)
    fmt.Println(str)

}
字符串

四、指针

指针:是一种存储变量内存地址的变量。

//指针
package main

import "fmt"

func main() {
    //&取地址符号
    //* 放在类型旁边,表示指向这个类型的指针
    //* 放在变量旁边,表示解引用(反解)
    //a:=10
    //b就是一个指针 指向int类型的指针
    //b:=&a
    //d:="sss"
    //var c *string=&d
    //var b *int =&a
    //fmt.Println(b)
    //fmt.Println(*b)
    //c:=&b
    //var c **int=&b
    //fmt.Println(*(*c))
    //指针的零值(Zero Value),nil类型
    //var a *int
    //fmt.Println(a)
    //向函数传递指针参数
    //a:=10
    ////b:=&a
    ////test6(b)
    ////fmt.Println(a)
    //test7(a)
    //fmt.Println(a)
    //func test6(b *int)  {
    //    //*b 就是 a  a++
    //    *b++
    //原来a的值也会被修改
    //    fmt.Println(*b)
    //}
    //func test7(b int)  {
    //    b++
    //原来a的值不会改变
    //    fmt.Println(b)

    //不要向函数传递数组的指针,而应该使用切片
    //var a [100]int
    ////test9(&a)
    ////fmt.Println(a)
    //test10(a[:])
    //fmt.Println(a)
    //Go 不支持指针运算

}
// 若向函数传递指针则数组指针的长度写死了,受众范围小
func test9(a *[4]int)  {
    (*a)[0]=999
    //底层数组也会受到影响
    fmt.Println(a)
}
func test10(a []int)  {
    //使用切片同样可以修改底层数组
    a[0]=999
    fmt.Println(a)

}
//}
指针相关用法及特点

五、结构体

package main

//结构体:是一系列属性的集合
//定义一个人结构体

//type关键字 结构体名字 struct{}
//type Person struct {
//    name string
//    sex ,age int
//
//}
//匿名字段表示字段没有名字
//type Person struct {
//    string
//    int
//}
//嵌套结构体
//type Person struct {
//    name string
//    sex ,age int
//    hobby Hobby
//
//}
//type Hobby struct {
//    id int
//    name string
//}
//结构体嵌套+匿名字段
type Person struct {
    name string
    sex ,age int
    Hobby

}
type Hobby struct {
    id int
    //hobbyname string
    name string
}

func main() {
    //person  :=Person{}
    //定义没有初始化
    //结构体是值类型
    //var person Person
    //var person Person=Person{name:"lqz"}
    //var person Person=Person{"lqz",1,19}
    ////person.name="lqz"
    //fmt.Println(person.name)
    //匿名结构体
    //age:=10
    //name:="lqz"
    //
    //a:=struct {
    //    name string
    //    age int
    //}{"lqz",19}
    //fmt.Printf(a.name)

    //结构体的零值
    //结构体指针
    //p:=Person{name:"lqz"}
    ////pPoint:=&p
    //var pPoint *Person=&p
    ////fmt.Println(pPoint)
    ////fmt.Println((*pPoint).name)
    //可以直接指针.变量名来获取
    //fmt.Println(pPoint.name)
    //匿名字段(用作变量提升)
    //p:=Person{"lqz",19}
    //用类型名来代替变量名
    //p:=Person{string:"lqz",int:19}
    //fmt.Println(p.string)

    //嵌套结构体
    //p:=Person{name:"lqz",hobby:Hobby{10,"篮球"}}
    //p:=Person{name:"lqz",hobby:Hobby{id:10,name:"篮球"}}
    //p.hobby.id=101
    //
    //fmt.Println(p.hobby.name)
    //结构体嵌套加匿名字段
    //p:=Person{name:"lqz",Hobby:Hobby{10,"篮球"}}
    ////取p中的hobbyname
    //fmt.Println(p.Hobby.hobbyname)
    //fmt.Println(p.hobbyname)
    //变量提升过程中如果有重名的,就不提升了
    //p:=Person{name:"lqz",Hobby:Hobby{10,"篮球"}}
    //fmt.Println(p.Hobby.name)
    //fmt.Println(p.name)
    //结构体相等性

}
结构体相关用法

六、方法

方法:方法其实就是一个函数,在func关键字和方法名之间加入了一个特殊的接收器类型,接收器可以是结构体类型,或者非结构体类型,接收器是可以在方法的内部访问的

package main

import "fmt"

//方法     其实就是一个函数

type Person struct {
    name string
    age int
    sex int
}


//语法
//func (a Person) getName()  {
//
//}
//方法给对象用
//给Person结构体加一个打印名字的方法
func (a Person)printName()  {
    fmt.Println(a.name)
}
//func (a Person)changeName(name string)  {
//    a.name=name
//    fmt.Println(a)
//}
func (a *Person)changeName(name string)  {
    a.name=name
    fmt.Println(a)
}
//func printName(a Person)  {
//    fmt.Println(a.name)
//}
//func printName(a *Person)  {
//    fmt.Println(a.name)
//}
func main() {
    //var p *Person=&Person{name:"lqz"}
    //这种也可以,go给你处理了
    //var p Person=Person{name:"lqz"}
    //p.changeName("egon")
    值类型的接收器,不会影响原p的值
    //fmt.Println(p)
    //p.printName()
    //为什么我们已经有函数了还需要方法呢
    //执行函数
    //printName(p)
    //printName(&p)

    //指针接收器与值接收器
    //func (值)changeName(name string):在内部修改值,不会影响外部的值
    //func (指针)changeName(name string):在内部修改值,会影响外部的值

    //那么什么时候使用指针接收器,什么时候使用值接收器
    //想修改原值,就用指针接收器
    //匿名字段的方法


}
方法

非结构体上的方法:

package main

import "fmt"

//在非结构体上的方法


//重命名
type MyInt int


func (i *MyInt)add()  {
    (*i)++
    fmt.Println(*i)
}

func main() {
    var a MyInt=10
    a.add()
    fmt.Println(a)
}
非结构体上的方法

在方法中使用值接收器 与 在函数中使用值参数
在方法中使用指针接收器 与 在函数中使用指针参数

package main

import "fmt"

//在方法中使用值接收器 与 在函数中使用值参数
//在方法中使用指针接收器 与 在函数中使用指针参数



type Person2 struct {
    name string
    age int
    sex int
}
//方法中使用值接收器
func (a Person2)printName()  {
    fmt.Println(a.name)

}
//方法中使用指针接收器
func (a *Person2)printName2()  {
    fmt.Println(a.name)
}
//函数中使用值参数
func printName(a Person2)  {
    fmt.Println(a.name)
}
//在函数中使用指针参数
func printName2(a *Person2)  {
    fmt.Println(a.name)
}

func main() {
    //p:=&Person2{name:"lqz"}
    //调用值接收器
    //p.printName()
    //调用指针接收器
    //p.printName2()
    //调用值函数
    //printName(p)
    //调用指针函数
    //printName2(&p)
    //方法中:
    //不管是指针接收器还是值接收器,都可以使用值来调用
    //不管是指针接收器还是值接收器,都可以使用指针来调用
    //函数中:
    //是什么参数,就得传什么参数







}
值接收器与指针接收器

七、接口

接口:在面向对象中,接口一般定义一个对象的行为,接口只是制定了对象应该做什么,至于如何实现这个行为,则由对象本身去决定。

 

posted @ 2019-12-11 22:26  1640808365  阅读(532)  评论(0编辑  收藏  举报