zoukankan      html  css  js  c++  java
  • Go语言学习(二)

    1、递归
    递归:自己调用自己
    递归适合处理那种问题相同,问题的规模越来越小的场景
    递归一定要有一个明确的退出条件

    func main(){
    	fmt.Println(f(5))
    }
    
    func f(n uint64) uint64{
    	if n == 1{
    		return 1
    	}
    	return n * f(n-1)
    } 
    

    2、定义类型和定义别名

    //自定义类型
    type myint int
    //定义别名
    type youint = int
    
    func main(){
    	var n myint
    	n = 100
    	fmt.Println(n)
    	fmt.Printf("%T
    ",n)
    
    	var m youint
    	m = 500
    	fmt.Println(m)
    	fmt.Printf("%T
    ",m)
    }
    

    效果如下所示:

    PS D:go> go run f.go
    100
    main.myint
    500
    int
    

    3、匿名结构体
    要理解匿名结构体的应用方向

    func main() {
    	//匿名结构体主要是用于临时场景
        var s struct {
    		name string
    		age int
    	}
    	s.name="超峰"
    	s.age = 20
    	fmt.Printf("%v
    ",s)
    }
    

    4、创建指针类型的结构体

    
    type person  struct{
    	name,sex string
    }
    
    // go语言里面函数永远传的是拷贝
    func f(p person){
    	p.sex = "女"   // 修改额是副本的sex,而不是原来的sex
    }
    
    func f1(p *person){
    	//(*p).sex = "女"   //根据内存地址找到哪个变量,修改的就是原来的变量
    	p.sex = "女"  //跟上面的都是一个效果,程序会自动判断p是什么类型,自动转化成(*p),这是语法糖
    }
    
    
    func main() {
    	var p person
    	p.name ="超峰"
    	p.sex = "男"
    	f(p)
    	fmt.Println(p.sex)
    	f1(&p)
    	fmt.Println(p.sex)
    }
    

    效果如下:

    PS D:go> .f.exe
    男
    女
    

    指针类型分析

    func main(){
    	var a = 10
    	b := &a
    	fmt.Printf("%T
    ",b)    //打印b的类型
    	fmt.Printf("%p
    ",b)   //以十六进制显示  ,b指针保存的是a的内存地址
    	fmt.Printf("%v
    ",b)   //以默认格式显示
    	fmt.Printf("%p
    ",&b)   //打印b指针对应的内存地址,因为b指针也有自己的内存地址
    }
    

    效果如下所示:

    PS D:go> .g.exe        
    *int
    0xc0000ac068
    0xc0000ac068
    0xc0000d8018
    

    结构体类型的指针

    type person  struct{
    	name,sex string
    }
    
    
    func main() {
    	//结构体指针1
    	var p2 = new(person)    //p2是一个指针类型的结构体
    	p2.sex = "男"
    	fmt.Printf("%s
    ",(*p2).sex)
    	fmt.Printf("%s
    ",p2.sex)
    	fmt.Printf("%T
    ",p2)    //得到指针类型
    	fmt.Printf("%p
    ",p2)      //p2保存的就是一个内存地址
    	fmt.Printf("%p
    ",&p2)     //求p2的内存地址
    
    	//结构体指针2
    	// 2.1、key-value方式初始化
    	var p3 = person{
    		name: "特朗普",
    		sex: "男",
    	}
    	fmt.Printf("%#v
    ",p3)
    
    	// 2.2、值传递的方式初始化
    	var p4 = person{
    		"小王子",
    		"男",
    	}
    	fmt.Printf("%#v
    ",p4)
    }
    

    效果如下所示:

    PS D:go> .f.exe
    男
    男
    *main.person
    0xc00005c3c0
    0xc000006028
    main.person{name:"特朗普", sex:"男"}
    main.person{name:"小王子", sex:"男"}
    

    5、构造函数

    type person struct{
    	name string
    	age int
    }
    
    type dog struct{
    	name string
    }
    
    //构造函数:约定俗称用new开头
    //返回的是结构体还是结构体指针
    //当结构体比较大的上海尽量使用结构体指针,减少程序的内存开销
    func newPerson(name string, age int) *person{
    	return &person {
    		name: name,
    		age : age,
    	}
    }
    
    func newdog(name string) dog{
    	return dog{
    		name: name,
    	}
    }
    
    func main(){
    	res1 := newPerson("超峰",20)
    	fmt.Println(*res1)
    	res2 := newdog("Mike")
    	fmt.Println(res2)
    }
    

    效果如下所示:

    PS D:go> .f.exe
    {超峰 20}
    {Mike}
    

    构造函数和方法区别

    type dog struct {
    	name string
    
    }
    
    
    // 构造函数
    func newDog(name string) dog{
    	return dog{
    		name: name,
    	}
    }
    
    //方法是作用于特定类型的函数
    // 接受者表示的是调用该方法的具体类型变量,多用类型名首字母小写表示,不建议使用this,self来表示
    func (d dog) wang(){
    	fmt.Printf("%s: 汪汪汪",d.name)
    }
    
    func main(){
    	d1 := newDog("Mike")
    	d1.wang()
    }
    

    效果如下所示L:

    PS D:go> .g.exe
    Mike: 汪汪汪
    

    5、值传递和指针传递的区别
    先说说什么时候应该使用指针类型的接收者
    a、需要修改接收者中的值
    b、接收者是拷贝代码比较大的对象
    c、保证一致性,如果使用了指针传递的方式,尽量都使用这种方法

    举个例子:

    package main
    
    import "fmt"
    
    type dog struct{
    	name string
    }
    
    type person struct{
    	name string
    	age int
    }
    
    func newPerson(name string,age int) person{
    	return person{
    		name: name,
    		age: age,
    	}
    }
    
    func newDog(name string) dog{
    	return dog{
    		name: name,
    	}
    }
    
    // 使用值接收者:传拷贝进去
    func (d dog)wang(){
    	fmt.Printf("%s:汪汪汪
    ",d.name)
    }
    
    // 指针接收者:传内存地址进去
    func (p *person)guonian(){
    	p.age++
    }
    
    func main(){
    	d1 := newDog("Mike")
    	d1.wang()
    	p1 := newPerson("John",20)
    	p1.guonian()   //相当于把p1的地址传到guonian()这个函数里面,这样子写比较好理解(&p1).guonian(),但实际上不这样用
    	fmt.Println(p1.name,p1.age)
    }
    

    效果如下所示:

    PS D:go> .f.exe
    Mike:汪汪汪
    John 21
    

    顺便补充一个自定义类型的知识点

    // 不能给别的包里面的类型增加自定义方法,只能给自己的包里的类型添加方法
    type myint int
    func (m myint) f1(){
    	fmt.Println("hello")
    }
    
    func main(){
    	m := myint(100)  // 与int(100)类似的效果。
    	m.hello
    }
    

    函数版学生管理系统

    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    type student struct{
    	id int
    	name string
    }
    
    var (
    	allstudent map[int]*student   //变量声明
    )
    
    func showAllstudent() {
    	for k,v := range allstudent{  // map里面存储的是 map[1:{1,"Mike"},2:{2:"John"}]
    		fmt.Printf("学生id是: %d, 姓名是: %s
    ",k,v.name)  
    	}
    }
    
    func newstu(id int,name string) *student{
    	return &student{
    		name: name,
    		id: id,
    	}
    }
    
    func addstudent() {
    	var (
    		id int
    		name string
    	)
    	fmt.Print("请输入增加的学号id: ")
    	fmt.Scanln(&id)
    	fmt.Print("请输入增加的学生姓名: ")
    	fmt.Scanln(&name)
    	stu := newstu(id,name)
    	allstudent[id] = stu
    	fmt.Println("增加成功")
    }
    
    func deletestudent(){
    	var (
    		id int
    	)
    	fmt.Print("请输入你要删除的学号id: ")
    	fmt.Scanln(&id)
    	delete(allstudent,id)
    	fmt.Println("删除成功")
    }
    
    func main(){
    	allstudent  = make(map[int]*student,48)
    	for{
    		fmt.Printf("欢迎来到学生管理系统")
    		fmt.Println(`
    		1、查看所有学生
    		2、增加学生
    		3、删除学生
    		4、退出
    		`)
    
    		fmt.Printf("请输入你要操作的序号: ")
    		var choice int
    		fmt.Scanln(&choice)
    	//	fmt.Printf("你当前输入的序号是: %d",choice)
    
    		switch choice {
    		case 1:
    			showAllstudent()
    		case 2:
    			addstudent()
    		case 3:
    			deletestudent()
    		case 4:
    			os.Exit(1)
    		default:
    			fmt.Println("滚")
    		}
    	}
    }
    

    6、匿名结构体

    package main
    
    import (
    	"fmt"
    )
    
    type address struct{
    	provice string
    	city string
    }
    
    
    type person struct{
    	name string
    	age int
    	addr address
    }
    type company struct{
    	name string
    	addr address
    }
    func main(){
    	p1 := person {
    		name: "Mike",
    		age: 20,
    		addr: address{
    			provice: "北京",
    			city: "朝阳",
    		},
    	}
    
    	c1 := company {
    		name: "牛卡福",
    		addr: address {
    			provice: "北京",
    			city: "朝阳",
    		},
    	}
    
    	fmt.Println(p1)
    	fmt.Println(p1.name,p1.addr.city,p1.addr.provice)
    	fmt.Println("----------------------------")
    	fmt.Println(c1)
    	fmt.Println(c1.name,c1.addr.provice)
    }
    

    7、结构体之继承
    如下例子所示:狗继承了动物会走的特性,狗调用自己会叫的特性,同时继承了动物会走的特性

    type animal struct{
    	name string
    }
    
    func (a animal) move(){
    	fmt.Printf("%s会动
    ",a.name)
    }
    
    type dog struct {
    	feet uint8
    	animal
    }
    
    func (d dog)wang(){
    	fmt.Printf("%s会叫: 汪汪汪
    ",d.name)
    }
    
    func main(){
    	f1 := animal{name: "动物"}
    	f1.move()
    	f2 := dog{
    		feet: 4,
    		animal: animal{
    			name: "狗",
    		},
    	}
    	f2.wang()
    	f2.move()
    }
    

    效果如下所示:

    PS D:go> .i.exe        
    动物会动
    狗会叫: 汪汪汪
    狗会动
    

    8、结构体与json
    1、序列化:把Go语言中的结构体变量转化为json格式的字符串
    2、反序列化:把json格式的字符串转化为Go语言中能够识别的结构体变量

    例子:

    package main
    
    import (
    	"fmt"
    	"encoding/json"
    )
    
    type person struct {
    	name string
    	age int
    }
    
    func main(){
    	p1 := person{
    		name: "Mike",
    		age: 18,
    	}
    	b,err := json.Marshal(p1)
    	if err != nil{
    		fmt.Printf("Marshal failed, err: %v",err)
    		return
    	}
    	// 将返回的字节强转为string字符串
    	fmt.Printf("%#v
    ",string(b))
    }
    

    效果如下所示:

    PS D:go> .i.exe
    "{}"
    

    我们使用了%#v,这是以go语法来进行了打印。看的出来是转化成了字符串。
    但是我们发现里面的json字串是空的,这是因为结构体的字段名需要大写,我们是把main包里面的结构体字段传入到json包里面,字段小写的话是穿不了的,需要改成首字母大写的形式,如下所示:

    # 这里只修改部分代码即可
    type person struct {
    	Name string
    	Age int
    }
    

    效果如下所示

    PS D:go> .i.exe        
    "{"Name":"Mike","Age":18}"
    

    看的出来现在已经转化了,比较成功。
    可以把%#v改成%v,这样子的话打印出来的结果里面就不会有双引号了,是默认打印的结果,如下所示

    PS D:go> .i.exe        
    {"Name":"Mike","Age":18}
    

    上面这种用法会用在前后端的交互中,有时候前端要接收全部小写的单词,那么我们上面是返回的结果是首字母大写的字段,所以这是不行的,可以如下所示进行修改

    type person struct {
    	Name string `json:"name"`
    	Age int 	`json:"age"`
    }
    # 后面都不需要修改,再看下效果
    

    效果

    PS D:go> .i.exe        
    {"name":"Mike","age":18}
    

    这返回的结果中,就是小写了,符合前端需要的标准

    接下来演示反序列化的代码

    package main
    
    import (
    	"fmt"
    	"encoding/json"
    )
    
    type person struct {
    	Name string `json:"name"`
    	Age int 	`json:"age"`
    }
    
    func main(){
    	p1 := person{
    		Name: "Mike",
    		Age: 18,
    	}
    	b,err := json.Marshal(p1)
    	if err != nil{
    		fmt.Printf("Marshal failed, err: %v",err)
    		return
    	}
    	// 将返回的字节强转为string字符串
    	fmt.Printf("%v
    ",string(b))
    
    	//反序列化
    	str := `{"name":"John","age":20}`
    	var p2 person
    
    	json.Unmarshal([]byte(str), &p2)   //注意这里需要传入指针,传指针式为了能在json.Unmarshal内部修改p2的值
    	fmt.Printf("%v
    ", p2)
    }
    

    效果如下所示:

    PS D:go> .i.exe
    {"name":"Mike","age":18}
    {John 20}
    

    知识点总结:
    1、架构体内部的字段首字母要大写,不大写别人是访问不道德
    2、反序列化需要传递指针

    回顾和总结

    package main
    
    import (
    	"fmt"
    )
    
    type tmp struct{
    	id int
    	name string
    }
    
    type person struct{
    	name string
    	age int
    }
    
    func newPerson(name string,age int) person {
    	return person{
    		name: name,
    		age: age,
    	}
    }
    
    //只有接收者类型的变量才可以调用
    func (p person)hoppy(str string){
    	fmt.Printf("%s的爱好是: %s
    ",p.name,str)
    }
    
    //下面这种是修改的结构体的副本
    func (p person)guonian2(){
    	p.age++
    }
    
    //指针接收者,强烈建议使用
    //当需要修改结构体的变量的值的时候,就可以使用指针接收者
    func (p *person)guonian(){
    	p.age++
    }
    
    func main(){
    	var b = tmp{100,"John"}
    	fmt.Println(b)
    
    	var a = struct{
    		id int
    		name string
    	}{10,"Mike"}
    	fmt.Println(a)
    
    	// 结构体的实例化的三种方法
    	var p1 person
    	p1.name = "John"
    	p1.age = 20
    
    	//匿名返回值
    	p2 := person{"Simon",30}
    
    	//构造函数返回值,返回值的是对应结构体类型
    	p3 := newPerson("Mike",40)
    	fmt.Println(p1,p2,p3)
    
    	p1.hoppy("羽毛球")
    	p2.hoppy("篮球")
    	p3.hoppy("网球")
    
    	p1.guonian()
    	p2.guonian()
    	p3.guonian()
    	fmt.Println(p1,p2,p3)
    
    	var f = "Mike"
    	fmt.Printf("%v",[]byte(f))
    }
    

    效果如下所示:

    PS D:go> go build .k.go
    PS D:go> .k.exe        
    {100 John}
    {10 Mike}
    {John 20} {Simon 30} {Mike 40}
    John的爱好是: 羽毛球
    Simon的爱好是: 篮球
    Mike的爱好是: 网球
    {John 21} {Simon 31} {Mike 41}
    [77 105 107 101]
    

    补充两个知识点
    1、类型别名只是在代码编写过程周有效,编译完成转换就不存在
    2、内置的byte和rune都是类型别名
    3、字符串类型可以和byte类型的切片进行转换

    9、接口
    接口的定义

    type 接口名 interface {
      方法名1(参数1, 参数2....)(返回值1,返回值2...)
      方法名2(参数1, 参数2....)(返回值1,返回值2...)
      ......
    }
    

    接口的实现
    一个变量如果实现了接口中规定的所有的方法,那么这个变量就实现了这个接口,可以称为这个接口类型的变量

    type animal interface {
    	move()
    	eat(string)
    }
    
    type cat struct{
    	name string
    	feet int8
    }
    
    func (c cat)move(){
    	fmt.Println("猫会动")
    }
    
    func (c cat)eat(s string){
    	fmt.Printf("猫吃%s
    ",s)
    }
    
    
    type chicken struct{
    	feet int8
    }
    
    func (c chicken) move(){
    	fmt.Println("鸡会动")
    }
    
    func (c chicken)eat(s string){
    	fmt.Printf("鸡吃%s
    ",s)
    }
    
    func main(){
    	var a1 animal //定义一个接口类型的变量,默认是nil
    
    	bc := cat{   //定义一个cat类型的变量bc
    		name: "蓝猫",
    		feet: 4,
    	}
    
    	a1 = bc
    	fmt.Println(a1)
    	a1.move()
    	a1.eat("猫粮")
    	//查看类型
    	fmt.Printf("%T
    ",a1)
    }
    

    效果如下:

    PS D:go> .l.exe      
    {蓝猫 4}
    猫会动
    猫吃猫粮
    main.cat
    

    10、使用值接收者实现接口与使用指针接收者实现接口的的方法

    使用值接收者实现接口,结构体类型和结构体指针类型的变量都能存
    使用指针接收者实现接口只能存结构体指针类型的变量

    type animal interface {
    	move()
    	eat(string)
    }
    
    type cat struct{
    	name string
    	feet int8
    }
    
    //使用指针接收者实现了接口的所有方法
    func (c *cat)move(){
    	fmt.Println("猫会动")
    }
    
    func (c *cat)eat(s string){
    	fmt.Printf("猫吃%s
    ",s)
    }
    
    
    type chicken struct{
    	feet int8
    }
    
    func (c chicken) move(){
    	fmt.Println("鸡会动")
    }
    
    func (c chicken)eat(s string){
    	fmt.Printf("鸡吃%s
    ",s)
    }
    
    func main(){
    	var a1 animal //定义一个接口类型的变量,默认是nil
    
    	bc := cat{   //定义一个cat类型的变量bc
    		name: "蓝猫",
    		feet: 4,
    	}
    
    	a1 = &bc  //实现animal这个接口的cat的指针类型
    	fmt.Println(a1)
    	a1.move()
    	a1.eat("猫粮")
    
            bc1 := &cat{name:"白猫",feet:4}
    	a1 = bc1
    	a1.move()
    	a1.eat("小鱼干")
    
    }
    

    效果如下所示L:

    PS D:go> .l.exe      
    &{蓝猫 4}
    猫会动
    猫吃猫粮
    猫会动
    猫吃小鱼干
    

    接口嵌套

    type Animal1 interface {
    	SetName(string)
    }
    
    type Animal2 interface {
    	GetName() string
    }
    
    type Animal interface{
    	Animal1
    	Animal2
    }
    
    type Dog struct{
    	name string
    }
    
    func (d *Dog)SetName(name string){
    	d.name = name
    }
    
    func (d *Dog)GetName()string{
    	return d.name
    }
    
    func main(){
    	var dog = &Dog{name:"Mike",}
    	var d Animal
    	d = dog
    	d.SetName("小狗")
    	fmt.Println(d.GetName())
    }
    

    效果如下所示:

    PS D:go> .l.exe
    小狗
    

    匿名函数的补充
    匿名函数就是没有名字的函数

    func main(){
    	f := func(i int){
    		fmt.Printf("Hello: %d
    ",i)
    	}
    	f(2)
    
    	f1 := func(i int){
    		fmt.Printf("结果是: %d
    ",i*i*i)
    	}
    	f1(3)
    
    }
    

    效果如下所示:

    PS D:go> .l.exe      
    Hello: 2
    结果是: 27
    

    11、空接口
    当不知道保存什么类型的值的时候,可以定义一个空接口类型

    func main(){
    	var a map[string]interface{}
    	a = make(map[string]interface{},48)
    	a["name"] = "Mike"
    	a["年龄"] =  20
    	a["hobby"] = [...]string{"唱","跳","rap"}
    	fmt.Println(a)
    
    }
    

    效果如下所示:

    PS D:go> .l.exe
    map[hobby:[唱 跳 rap] name:Mike 年龄:20]
    

    类型断言:
    主要是使用变量.(类型)方式来判定

    func main(){
    	var a interface{}   //声明一个空接口类型
    	a = 100   //此时a是int64类型的
    	v1,ok := a.(int8)
    	if ok{
    		fmt.Println("猜对了,是int8类型",v1)
    	}else {
    		fmt.Println("猜错了")
    	}
    
    	//第二种方式,使用类型断言,用type判断这是什么类型
    	switch v2 := a.(type) {
    	case int8:
    		fmt.Println("int8",v2)
    	case int16:
    		fmt.Println("int16",v2)
    	case int32:
    		fmt.Println("int32",v2)
    	case int64:
    		fmt.Println("int64",v2)
    	case string:
    		fmt.Println("string",v2)
    	case int:
    		fmt.Println("int",v2)
    	}
    }
    

    效果如下所示:

    PS D:go> .
    .exe
    猜错了
    int 100
    

    12、包package
    如果想在一个包中引用另外一个包里面的标识符(如变量,常量,类型,函数等)时,该标识符必须是对外可见的(public)。在go语言中只需要将标识符的首字母大写就可以让标识符对外可见了,这也是为什么我们使用fmt.Println()的时候,P这个字母大写的原因。
    使用方式如下:
    a、先定义GOPATH变量,这是Go的工作空间
    可以使用go env命令查看。
    我这里是windows机器,假设GOPATH=D:go
    b、定义src目录
    此时需要在D:go下面有一个src目录,手动创建。
    c、接下来
    D:gosrc目录下创建clac目录,并写入文件

    package calc
    
    func Sum(x int,y int) int{           // Sum首字母大写,否则其他包找不到这个函数
    	return x + y
    }
    

    d、接着是main包
    必须有一个main包

    package main
    
    import (
    	"calc"    //这里找的就是D:gosrccalc目录
    	"fmt"
    )
    
    func main(){
    	s := calc.Sum(10,20)
    	fmt.Println(s)
    }
    

    包的自定义别名

    import 别名 项目
    

    13、init()初始化函数
    go语言程序执行时导入包语句会自动触发内部的init()函数的调用,需要注意,init()函数没有参数,也没返回值,init()函数是自动被调用执行,不能在代码中主动调用它,比如

    package calc
    
    import (
    	"fmt"
    )
    func init(){
    	fmt.Println("这是sum函数")
    }
    func Sum(x int,y int) int{
    	return x + y
    }
    

    main包

    package main
    
    import (
    	"calc"
    	"fmt"
    )
    
    
    func init(){
    	fmt.Println("这是main函数")
    }
    
    func main(){
    	s := calc.Sum(10,20)
    	fmt.Println(s)
    }
    

    执行效果如下所示:

    PS D:go> .m.exe        
    这是sum函数
    这是main函数
    30
    

    如下流程图所示:

    还有一个初始化函数的执行顺序如下图所示:

    14、文件操作
    使用bufio模块

    package main
    import (
    	"fmt"
    	"os"
    	"io"
    	"bufio"
    )
    
    func main(){
    	fileObj,err := os.Open("./e.go")
    	if err != nil{
    		fmt.Println("Open file failed!!!")
    		return
    	}
    	//记得关闭文件
    	defer fileObj.Close()
    	//创建一个用来从文件中读内容的对象
    	reader := bufio.NewReader(fileObj)
    	// 循环打印每一行内容
    	for{
    		line,err := reader.ReadString('
    ')
    		// 读取到文件末尾就退出
    		if err == io.EOF {
    			return
    		}
    		if err != nil{
    			fmt.Printf("read line failed")
    			return
    		}
    		fmt.Print(line) //这里要使用print, 不要换行
    	}
    }
    

    文件内容比较多,这里不再展示了

    使用ioutil工具读取文件,这个工具大概每次读取512个字节

    package main
    import (
    	"fmt"
    	"io/ioutil"
    )
    
    func main(){
    	ret,err := ioutil.ReadFile("./e.go")
    	if err != nil{
    		fmt.Println("文件读取失败!!!")
    		return
    	}
            //ret是字节,这里需要string转化一下
    	fmt.Print(string(ret))
    }
    

    15、写文件操作得几种方式

    package main
    import (
    	"fmt"
    	"bufio"
    	"os"
    	"io/ioutil"
    )
    
    
    func writefileDemo1(){
    	// 读写文件,如果没有就创建,追加文件内容
    	fileObj,err := os.OpenFile("./test.txt",os.O_WRONLY|os.O_CREATE|os.O_APPEND,0644)
    	if err != nil{
    		fmt.Println("Open file failed,err:%v",err)
    		return
    	}
    	fileObj.Write([]byte("Hello world
    "))
    	fileObj.WriteString("You are welcome
    ")
    	fileObj.Close()
    }
    
    func writefileDemo2(){
    	fileObj,err := os.OpenFile("./test.txt",os.O_WRONLY|os.O_CREATE|os.O_APPEND,0644)
    	if err != nil{
    		fmt.Println("Open file failed,err:%v",err)
    		return
    	}
    	defer fileObj.Close()
    	wr := bufio.NewWriter(fileObj)
    	wr.WriteString("hello沙河")
    	wr.Flush() //将缓存中得内容写入文件
    
    }
    
    func writefileDemo3(){
    	//下面这种不能追加,需要额外的机制来解决
    	str := "hello world"
    	err := ioutil.WriteFile("./test.txt", []byte(str),0666)
    	if err != nil{
    		fmt.Println("Write file failed ,err:",err)
    		return
    	}
    }
    
    func main(){
    
    	//writefileDemo1()
    	//writefileDemo2()
    	writefileDemo3()
    
    	
    }
    

    补充知识点:

    使用fmt.Scanln(str)从终端读取得缺点是不能遇到空格,否则只能识别第一个空格前面的字符串,如下所示:

    func main(){
    	var str string
    	fmt.Print("请输入内容: ")
    	fmt.Scanln(&str)
    	fmt.Println("输入的内容是: ",str)
    }
    

    效果如下所示:

    PS D:go> .
    .exe
    请输入内容: chen chao feng
    输入的内容是:  chen
    

    用下面这种方法进行更改

    func main(){
    	var s string
    	reader := bufio.NewReader(os.Stdin)
    	fmt.Println("请输入内容: ")
    	s,_ = reader.ReadString('
    ')
    	fmt.Printf("你输入的内容是: %s
    ",s)
    }
    

    效果如下所示:

    PS D:go> .
    .exe      
    请输入内容: 
    Hello world
    你输入的内容是: Hello world
    

    go类型转换,字节和整型的转换

    //整形转换成字节
    func IntToBytes(n int) []byte {
      x := int32(n)
      bytesBuffer := bytes.NewBuffer([]byte{})
      binary.Write(bytesBuffer, binary.BigEndian, x)
      return bytesBuffer.Bytes()
    }
    //字节转换成整形
    func BytesToInt(b []byte) int {
      bytesBuffer := bytes.NewBuffer(b)
      
      var x int32
      binary.Read(bytesBuffer, binary.BigEndian, &x)
      
      return int(x)
    }
    

    16、时间的各种使用

    func main(){
    	now := time.Now()
    	fmt.Println(now)
    	fmt.Println(now.Year())
    	fmt.Println(now.Month())
    	fmt.Println(now.Day())
    	fmt.Println(now.Hour())
    	fmt.Println(now.Minute())
    	fmt.Println(now.Second())
    	fmt.Println("++++++++++++++++++++++++++++++++")
    	//时间戳,微秒
    	fmt.Println(now.Unix())
    	//纳秒
    	fmt.Println(now.UnixNano())
    	fmt.Println("++++++++++++++++++++++++++++++++")
    	
    	//time.Unix()
    	ret := time.Unix(1564803667, 0)
    	fmt.Println(ret)
    	fmt.Println(ret.Year())
    	fmt.Println(ret.Day())
    	fmt.Println("++++++++++++++++++++++++++++++++")
    
    	// 明天的这个时候
    	fmt.Println(now.Add(time.Hour * 24))
    	fmt.Println("################################")
    
    	//格式化时间输出。go是从诞生日这种格式来用的
    	fmt.Println(now.Format("2006-01-02"))
    
    	// 得到年月日时分秒的格式
    	fmt.Println(now.Format("2006/01/02 15:04:05"))
    
    	//将对应的格式解析成字符串类型的时间
    	timeObj, err := time.Parse("2006-01-02", "2021-08-20")
    	if err != nil {
    		fmt.Printf("parse time failesd, err: %v
    ",err)
    		return
    	}
    	fmt.Println(timeObj)
    	fmt.Println(timeObj.Unix())   //将对应的时间格式转化成其他的格式,非常好用
    }
    

    效果如下所示:

    PS D:go> .
    .exe        
    2021-08-20 19:32:26.007833 +0800 CST m=+0.003088801
    2021
    August
    20
    19
    32
    26
    ++++++++++++++++++++++++++++++++
    1629459146
    1629459146007833000
    ++++++++++++++++++++++++++++++++
    2019-08-03 11:41:07 +0800 CST
    2019
    3
    ++++++++++++++++++++++++++++++++
    2021-08-21 19:32:26.007833 +0800 CST m=+86400.003088801
    ################################
    2021-08-20
    2021/08/20 19:32:26
    2021-08-20 00:00:00 +0000 UTC
    1629417600
    

    17、获取文件的大小和文件名称

    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func main(){
    	//打开当前文件,os.Open()多用来读取文件
    	fileObj, err := os.Open("p.go")
    	if err != nil{
    		fmt.Printf("open file failed ,err: %v
    ", err)
    		return
    	}
    	// 1、文件对象的类型
    	fmt.Printf("%T
    ", fileObj)
    	// 2、获取文件对象的详细信息
    	fileInfo, err := fileObj.Stat()
    	if err != nil{
    		fmt.Printf("get file info failed, err: %v
    ", err)
    		return
    	}
    	fmt.Printf("文件大小是: %d B
    ",fileInfo.Size())
    	fmt.Printf("文件名是: %s
    ",fileInfo.Name())
    }
    

    效果如下所示:

    PS D:go> .p.exe      
    *os.File
    文件大小是: 560 B
    文件名是: p.go
    
  • 相关阅读:
    Django模型层进阶
    Django模型层相关
    BOM与DOM
    JavaScript入门
    HTML基础
    子查询/联合分组/all与any/视图/事务
    表的查询
    mysql的多表关系
    Mysql基本操作
    Spider_基础总结2_Requests异常
  • 原文地址:https://www.cnblogs.com/FengGeBlog/p/15111009.html
Copyright © 2011-2022 走看看