go语言练习课题

3 篇文章 0 订阅

day01

请获取字符串"hello我要杀了你这头猪",中有多少个中文。

字符和字节和字符串
go语言,字符串有一个特点,不能修改。
字符:用单引号包裹,单个字母,单个符号,单个文字
字符串:用双引号包裹。
字节:1byte=8bit
go语言中字符串都是UTF8编码,UTF8编码中一个汉字一般占用3个字节

Go 语言的内建函数 len(),可以用来获取切片、字符串、通道(channel)等的长度。下面的代码可以用 len() 来获取字符串的长度。

s := “hello我要杀了你这头猪”
fmt.Println(len(s))

29

go 语言写法:
package main

import (
	"fmt"
	"unicode"
)

func main() {
	s := "hello我要杀了你这头猪"
	chNum := 0
	for _, v := range s {
		if unicode.Is(unicode.Han, v) {
			chNum ++
		}
	}
	fmt.Println(chNum)
}

对应Python写法:
def main():
    s = "hello我要杀了你这头猪"
    num = 0
    for i in s:
        s_len = len(i.encode('utf-8'))
        print(s_len)
        if s_len == 3:
            num += 1
    return num


if __name__ == '__main__':
    ch_num = main()
    print(ch_num)

输出99乘法表

循环遍历的问题

go 语言写法:
package main

import "fmt"

func main() {
	for i := 1; i < 10; i++ {
		for j := 1; j <= i; j++ {
			fmt.Printf("%d * %d = %d ", j, i, i*j)
		}
		fmt.Println()
	}
}
对照Python写法
def main():
    for i in range(1, 10):
        for j in range(1, 10):
            if i >= j:
            	# python默认print中end='\n'也就是自带换行,取消自动换行:end='',
                print("%d * %d = %d " % (i, j, i * j), end='')
        print()


if __name__ == '__main__':
    main()
def main():
    for i in range(1, 10):
        w = 10 - i
        for j in range(w, 10):
            print("%d * %d = %d " % (j - w + 1, i, i * (j - w + 1)), end='')
        print()


if __name__ == '__main__':
    main()

day02

计算字符串中"how do you do"每个单词出现的次数。

分析:首先把字符串切开,然后再使用map进行统计,当某个单词已经存在的时候,其对应的值自动加一。

使用go
package main

import (
	"fmt"
	"strings"
)

func main() {
	newStr := "how do you do"
	s1 := strings.Split(newStr, " ")
	m1 := make(map[string]int, 10)
	for _, v := range s1 {
		if m1[v] != 0 {
			m1[v] = m1[v] + 1
		} else {
			m1[v] = 1
		}
	}
	for k, v := range m1 {
		fmt.Println(k, v)
	}
}
使用python
s1 = "how do you do"


def main():
    s1_list = s1.split(' ')
    s1_map = {}
    for i in s1_list:
        s1_map[i] = s1_map[i] + 1 if s1_map.get(i) else 1
    for k, v in s1_map.items():
        print(k, v)


if __name__ == '__main__':
    main()

day03

分金币

你有50枚金币,需要分配给以下几个人:Matthew,Sarah,Augustus,Heidi,Emilie,Peter,Giana,Adriano,Aaron,Elizabeth。
分配规则如下:
a. 名字中每包含1个’e’或’E’分1枚金币
b. 名字中每包含1个’i’或’I’分2枚金币
c. 名字中每包含1个’o’或’O’分3枚金币
d: 名字中每包含1个’u’或’U’分4枚金币
写一个程序,计算每个用户分到多少金币,以及最后剩余多少金币?
程序结构如下,请实现 ‘dispatchCoin’ 函数

package main

import "fmt"

var (
	coins = 50
	users = []string{
		"Matthew", "Sarah", "Augustus", "Heidi", "Emilie", "Peter", "Giana", "Adriano", "Aaron", "Elizabeth",
	}
	distribution = make(map[string]int, len(users))
)

func dispatchCoin() interface{} {
	for _, name := range users {
		nextCoins := coins
		for _, b := range name {
			switch b {
			case 'e', 'E':
				coins -= 1
			case 'i', 'I':
				coins -= 2
			case 'o', 'O':
				coins -= 3
			case 'u', 'U':
				coins -= 4
			}
		}
		distribution[name] = nextCoins - coins
	}
	fmt.Println(distribution)
	return coins
}

func main() {
	left := dispatchCoin()
	fmt.Println("剩下:", left)
}

使用python

name_list = ["Matthew", "Sarah", "Augustus", "Heidi", "Emilie", "Peter", "Giana", "Adriano", "Aaron", "Elizabeth"]
coins = 50


def dispatch_coin(the_list, start_coins):
    name_map = {}
    for name in the_list:
        left_coins = start_coins
        for p in name:
            if p in ["e", "E"]:
                start_coins -= 1
            elif p in ["i", "I"]:
                start_coins -= 2
            elif p in ["o", "O"]:
                start_coins -= 3
            elif p in ["u", "U"]:
                start_coins -= 4
            else:
                pass
        name_map[name] = left_coins - start_coins
    print(name_map)
    return start_coins


def main():
    left = dispatch_coin(name_list, coins)
    print(left)


if __name__ == '__main__':
    main()

day04

面试题走台阶

假设有一段台阶,可以每次走一个,也可以每次走2个,那么一共有多少种走法。
递归。

package main

import "fmt"

func taijie(n uint64) uint64 {
	// 如果有一个台阶毫无疑问就是一种
	if n == 1 {
		return 1
	}
	// 如果有2个台阶,那有两种方法。
	if n == 2 {
		return 2
	}
	// 假设走到最后一步的时候,此时只有2种情况,那就是还有一个台阶或者还有2个台阶
	// 那么把走剩最后一步的前面走台阶的方式加在一起就是全部的走法
	return taijie(n-1) + taijie(n-2)
}

func main() {
	way := taijie(5)
	fmt.Printf("共有%d种走法", way)
}

python的写法

def tai_jie(n):
    if n == 1:
        return 1
    if n == 2:
        return 2
    return tai_jie(n - 1) + tai_jie(n - 2)


def main(n):
    ways = tai_jie(n)
    print("一共有%d种方法"% ways)


if __name__ == '__main__':
    main(5)

写一个学生管理系统函数版:

package main

import (
	"fmt"
	"os"
)

/*
写一个学生系统,不需要做多余的判断,考验结构体的使用。
*/
type studentInfo struct {
	id   uint32
	name string
}

var studentMap map[uint32]*studentInfo

func xiTong() {
	fmt.Println("欢迎来到学生系统!!")
	// 初始化学生数据
	studentMap = make(map[uint32]*studentInfo, 50)
	for {
		fmt.Println(`
		1. 查询
		2. 数据添加
		3. 数据删除
		4. 退出
		`)
		fmt.Print("请输入序列号:")
		var num uint
		fmt.Scanln(&num)
		switch num {
		case 1:
			showAllStudent()
		case 2:
			addStudent()
		case 3:
			deleteStudent()
		case 4:
			os.Exit(1)
		default:
			println("输入错误")
		}
	}
}

func deleteStudent() {
	fmt.Println("删除学生信息")
	var id uint32
	fmt.Println("请输入删除学生学号:")
	fmt.Scanln(&id)
	delete(studentMap, id)
}

func addStudent() {
	fmt.Println("添加学生信息")
	var id uint32
	var name string
	fmt.Println("请输入学号:")
	fmt.Scanln(&id)
	fmt.Println("请输入姓名:")
	fmt.Scanln(&name)
	p := &studentInfo{
		id:   id,
		name: name,
	}
	studentMap[id] = p
	fmt.Println(studentMap)
}

func showAllStudent() {
	fmt.Println("学生数据如下:")
	for i, v := range studentMap {
		fmt.Printf("学号:%d, 姓名:%s\n", i, v.name)
	}
}

func main() {
	xiTong()
}

面向对象对上一个代码进行更改

package main

import (
	"fmt"
	"os"
)

type xiTong struct {
	studentInfo
	studentMap map[uint32]*studentInfo
}

type studentInfo struct {
	id   uint32
	name string
}

//newStudentInfo 是studentInfo类型的构造函数
func (x xiTong) newStudentInfo(id uint32, name string) *studentInfo {
	return &studentInfo{
		id:   id,
		name: name,
	}
}

func (x xiTong) showAllStudents() {
	fmt.Println("学生数据如下:")
	for i, v := range x.studentMap {
		fmt.Printf("学号:%d, 姓名:%s\n", i, v.name)
	}
}

func (x xiTong) addStudent() {
	fmt.Println("添加学生信息")
	var id uint32
	var name string
	fmt.Println("请输入学号:")
	fmt.Scanln(&id)
	fmt.Println("请输入姓名:")
	fmt.Scanln(&name)
	p := x.newStudentInfo(id, name)
	x.studentMap[id] = p
	fmt.Println(x.studentMap)
}

func (x xiTong) deleteStudent() {
	fmt.Println("删除学生信息")
	var deleteID uint32
	fmt.Println("请输入删除学生学号:")
	fmt.Scanln(&deleteID)
	delete(x.studentMap, deleteID)
}

func start() {
	fmt.Println("欢迎来到学生系统!!")
	// 初始化系统
	var x xiTong
	// 初始化学生数据
	x.studentMap = make(map[uint32]*studentInfo, 50)
	for {
		fmt.Println(`
		1. 查询
		2. 数据添加
		3. 数据删除
		4. 退出
		`)
		fmt.Print("请输入序列号:")
		var num uint
		fmt.Scanln(&num)
		switch num {
		case 1:
			x.showAllStudents()
		case 2:
			x.addStudent()
		case 3:
			x.deleteStudent()
		case 4:
			os.Exit(1)
		default:
			println("输入错误")
		}
	}
}

func main() {
	start()
}

new和make的区别

二者都是用来做内存分配的。
make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身;
而new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。

序列化和反序列化的问题

当将一个对象转换为json的字符串的时候,我们需要用的go的序列化函数:json.Marshal(p1)
序列化:传入一个对象,比如一个结构体。此时我们调用的Marshal函数是json包的函数,传入的内容必须符合go语言要求的外部调用,首字母大写的方式。外部包的调用,被调用的变量首字母大写
反序列话:传入一个字符串,转换成一个结构体,此时调用json.Unmarshal,先初始化一个空结构体,然后将字符串序列化后传入,此时就需要改变原来的空结构体,由于函数传参传入的是参数副本,因此此时只有传入参数的指针,才可以修改需要被填入数据的空结构体。
函数传入参数,参数不是其本身,而是该参数拷贝的一个副本,如果需要进行修改操作,传入的参数必须为一个指针类型
如下例:

package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	type point struct {
	// 这里的结构体内部变量名称必须要首字母大写,因为首字母大写才能被外部函数获取到,如果要求输出格式,那就在后面添加:`json:"变量名"`
		X int `json:"x"` 
		Y int `json:"y"`
	}
	p1 := point{100, 200,}
	// 序列化:这个函数返回2个值,0是byte类型的切片,1是报错信息
	b, err := json.Marshal(p1)
	if err != nil{
		fmt.Printf("序列化出错了,err:%s",err)
	}
	fmt.Println(string(b))
	// 反序列化
	str1 := `{"x":10,"y":20}`
	var p2 point
	// 此时要将p2的指针传给函数,这样才能真正的把反序列化后的数据写入到要p2中
	err = json.Unmarshal([]byte(str1), &p2)
	if err != nil {
		fmt.Printf("反序列化出错了:%s", err)
	}
	fmt.Println(p2)
}

day05

1.写一个copy操作

package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	err := myCopy("1.txt", "2.txt")
	if err != nil {
		fmt.Println("copy file failed, err:", err)
		return
	}
	fmt.Println("copy finish!")
}

func myCopy(srcName string, dstName string) (err error) {
	// 读取数据
	src, err := os.Open(srcName)
	if err != nil {
		fmt.Printf("read file failed, err:%s", err)
		return
	}
	defer src.Close()
	// 准备被写入数据的文件
	dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0644)
	if err != nil {
		fmt.Printf("write file failed, err:%s", err)
		return
	}
	defer dst.Close()
	// 调用io.copy进行数据拷贝
	io.Copy(dst, src)
	return
}

2.模拟编写一个linux的cat操作文件。

写好之后,使用go build创建一个文件叫cat 然后执行:cat 文件1 文件2

package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"os"
)

func useBufio() {
	reader := bufio.NewReader(os.Stdin)
	readString, _ := reader.ReadString('\n')
	fmt.Println(readString)
}

func main() {
	// 1.从命令行获取到需要被cat的文件名称
	flag.Parse() //解析执行该文本的参数,多个参数用空格分开
	// 如果默认参数为0,则从标准输入获取内容
	if flag.NArg() == 0 {
		cat(bufio.NewReader(os.Stdin))
	}
	// 如果有多个参数,则,逐一打开
	for _, fileName := range flag.Args() {
		file, err := os.Open(fileName)
		if err != nil {
			// 输出到命令行
			fmt.Fprintf(os.Stdout, "reading %s failed, err:%s\n", fileName, err)
			continue
		}
		cat(bufio.NewReader(file))
	}

}

func cat(r *bufio.Reader) {
	// 2.打开文件
	for {
		readString, err := r.ReadString('\n')
		if err == io.EOF {
			// 上面设定是\n换行,如果最后一行没有输入换行符,即光标在行末,防止本行数据就会丢失
			if len(readString) != 0 {
				fmt.Print(readString)
			}
			break
		}
		if err != nil {
			fmt.Printf("file read err:%s\n", err)
			break
		}
		// 将要cat的信息输出到命令行
		fmt.Fprintf(os.Stdout, "%s", readString)
	}
	fmt.Println()
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值