从下往上看
package main
import (
"bufio"
"encoding/json"
"flag"
"fmt"
"io"
"io/ioutil"
"os"
)
type Monkey struct {
Name string
}
type BirdAble interface {
Flaying()
}
type FishAble interface {
Swimming()
}
func (this *Monkey) climbing() {
fmt.Println(this.Name, "会爬树...")
}
type LittleMonkey struct {
Monkey
}
func (this *LittleMonkey) Flaying() {
fmt.Println(this.Name, "学会了飞翔")
}
func (this *LittleMonkey) Swimming() {
fmt.Println(this.Name, "学会了游泳")
}
func test1() {
/*
对上面代码的小结
1) 当 A 结构体继承了 B 结构体,那么 A 结构就自动的继承了 B 结构体的字段和方法,并且可以直接使用
2) 当 A 结构体需要扩展功能,同时不希望去破坏继承关系,则可以去实现某个接口即可,因此我们可以认为:实现接口是对继承机制的补充.
实现接口可以看作是对 继承的一种补充
继承是被动的, 接口是主动的.
继承被动继承了父类结构体字段和方法; 而接口可以主动扩展某些功能
*/
monkey := LittleMonkey{
Monkey{Name: "悟空"},
}
monkey.climbing()
monkey.Flaying()
monkey.Swimming()
}
type Usb interface {
Start()
Stop()
}
type Phone struct {
name string
}
func (this Phone) Start() {
fmt.Println(this.name, "start working")
}
func (this Phone) Stop() {
fmt.Println(this.name, "Stop working")
}
func (this Phone) Call() {
fmt.Println(this.name, "phone can call")
}
type Camera struct {
name string
}
func (this Camera) Start() {
fmt.Println(this.name, "start working")
}
func (this Camera) Stop() {
fmt.Println(this.name, "Stop working")
}
func test2() {
var usbArr []Usb
var phone Phone = Phone{name: "apple"}
var camera Camera = Camera{name: "索尼"}
usbArr = append(usbArr, phone, camera)
for _, val := range usbArr {
val.Start()
if p1, ok := val.(Phone); ok {
p1.Call()
}
val.Stop()
}
}
type Point struct {
x int
y int
}
func test3() {
var a interface{}
var point Point = Point{1, 2}
a = point // ok
var b Point
// b = a // error
b, ok := a.(Point) // 一个空接口可以赋值任何对象, 但是当空接口对象要赋值给其他对象是需要转换
if !ok {
fmt.Println("转换失败")
return
}
fmt.Println(b)
var x interface{}
var b2 float32 = 1.1
x = b2
y, ok := x.(float32)
if !ok { // 练习给test2中Phone添加call方法, 当类型为Phoen时指向Call方法
fmt.Println("转换失败")
return
}
fmt.Printf("y 的类型是%T, 值是%v", y, y)
}
func TypeJudge(items ...interface{}) {
for index, x := range items {
switch x.(type) {
case bool:
fmt.Printf("第%v个参数%v, type 是 bool类型
", index, x)
case float32:
fmt.Printf("第%v个参数%v, type 是 float32类型
", index, x)
case float64:
fmt.Printf("第%v个参数%v, type 是 float64类型
", index, x)
case int, int32, int64:
fmt.Printf("第%v个参数%v, type 是 int, int32, int64类型
", index, x)
case string:
fmt.Printf("第%v个参数%v, type 是string类型
", index, x)
case Student:
fmt.Printf("第%v个参数%v, type 是Student类型
", index, x)
case *Student:
fmt.Printf("第%v个参数%v, type 是*Student类型
", index, x)
default:
fmt.Printf("第%v个参数%v,类型不确定
", index, x)
}
}
}
type Student struct {
Name string
}
func test4() {
var n1 float32 = 1.1
var n2 float64 = 1.1
var n3 int = 30
var n4 string = "fadsf"
n5 := 1000
var s1 Student = Student{Name: "alex"}
var s2 *Student = &Student{Name: "alex"}
TypeJudge(n1, n2, n3, n4, n5, s1, s2)
}
type AccountRecord struct {
Title string
Income float32
Desc string
Balance float32
}
type Account struct {
TotalAmount float32
Records []*AccountRecord
Loop bool
Key string
}
func test5() {
account := Account{}
account.Records = append(account.Records, &AccountRecord{})
fmt.Println(account.Key, account.TotalAmount, account.Records, account.Loop)
}
//TODO go 韩顺平 360-379项目2没做
func test6() {
filename := "C:/Users/yzt/Desktop/gitlab初始化使用.txt"
file, err := os.Open(filename)
defer file.Close()
if err != nil {
fmt.Println("文件打开失败, err: ", err)
}
// const (
// defaultBufSize = 4096
// )
// 创建一个reader对象,读取文件
reader := bufio.NewReader(file)
for {
str, err := reader.ReadString('
')
if err == io.EOF {
break
}
fmt.Print(str)
}
fmt.Println("file=%v", file)
err = file.Close()
if err != nil {
fmt.Println("关闭文件失败, err: ", err)
}
}
func test7() {
// ioutil不适合大文件
filename := "C:/Users/yzt/Desktop/gitlab初始化使用.txt"
content, err := ioutil.ReadFile(filename)
if err != nil {
fmt.Println("文件打开失败, err: ", err)
}
fmt.Printf("%v", string(content))
}
func test8() {
filename := "C:/Users/yzt/Desktop/test.txt"
file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
fmt.Println("文件打开失败, err: ", err)
return
}
defer file.Close()
str := "hello, Gardon
"
writer := bufio.NewWriter(file)
for i := 0; i < 5; i++ {
writer.WriteString(str)
}
writer.Flush()
}
func test9() {
filename := "C:/Users/yzt/Desktop/test.txt"
file, err := os.OpenFile(filename, os.O_WRONLY|os.O_TRUNC, 0666)
if err != nil {
fmt.Println("文件打开失败, err: ", err)
return
}
defer file.Close()
str := "你好, 尚硅谷
"
writer := bufio.NewWriter(file)
for i := 0; i < 5; i++ {
writer.WriteString(str)
}
writer.Flush()
}
func test10() {
filename := "C:/Users/yzt/Desktop/test.txt"
file, err := os.OpenFile(filename, os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
fmt.Println("文件打开失败, err: ", err)
return
}
defer file.Close()
str := "1233333333
"
//写入时,使用带缓存的 *Writer
writer := bufio.NewWriter(file)
for i := 0; i < 5; i++ {
writer.WriteString(str)
}
//因为 writer 是带缓存,因此在调用 WriterString 方法时,其实
//内容是先写入到缓存的,所以需要调用 Flush 方法,将缓冲的数据
//真正写入到文件中, 否则文件中会没有数据!!!
writer.Flush()
}
func test11() {
filename := "C:/Users/yzt/Desktop/test.txt"
file, err := os.OpenFile(filename, os.O_APPEND|os.O_RDWR, 0666)
if err != nil {
fmt.Println("文件打开失败, err: ", err)
return
}
defer file.Close()
reader := bufio.NewReader(file)
for {
str, err := reader.ReadString('
')
if err == io.EOF {
break
}
fmt.Print(str)
}
str := "尚硅谷!尚硅谷!尚硅谷!
"
//写入时,使用带缓存的 *Writer
writer := bufio.NewWriter(file)
for i := 0; i < 5; i++ {
writer.WriteString(str)
}
//因为 writer 是带缓存,因此在调用 WriterString 方法时,其实
//内容是先写入到缓存的,所以需要调用 Flush 方法,将缓冲的数据
//真正写入到文件中, 否则文件中会没有数据!!!
writer.Flush()
}
func test12() {
filename1 := "C:/Users/yzt/Desktop/test.txt"
filename2 := "C:/Users/yzt/Desktop/gitlab初始化使用.txt"
content, err := ioutil.ReadFile(filename2)
if err != nil {
fmt.Println("read file err: ", err)
return
}
// WriteFile会先将文件清空之后,在写入
err = ioutil.WriteFile(filename1, []byte(content), 0666)
if err != nil {
fmt.Println("writer file err: ", err)
return
}
}
func PathExists(path string) (isExists bool, err error) {
_, err = os.Stat(path)
if err == nil {
isExists = true
return
}
if os.IsNotExist(err) {
return
}
return
}
func test13() {
filename := "C:/Users/yzt/Desktop/test.txt"
flag, err := PathExists(filename)
if err != nil {
fmt.Println("文件不存在")
}
if flag {
fmt.Println("文件存在")
}
}
func CopyFile(dest string, src string) (written int64, err error) {
srcFile, err := os.Open(src)
if err != nil {
fmt.Println("opne file err: ", err)
return
}
defer srcFile.Close()
reader := bufio.NewReader(srcFile)
dstFile, err := os.OpenFile(dest, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
fmt.Println("opne file err: ", err)
return
}
writer := bufio.NewWriter(dstFile)
defer dstFile.Close()
written, err = io.Copy(writer, reader)
return
}
func test14() {
// copy图片
pngname := "C:/Users/yzt/Pictures/timg3.jpg"
pngname2 := "C:/Users/yzt/Pictures/timg2.jpg"
_, err := CopyFile(pngname2, pngname)
if err != nil {
fmt.Println("copy 文件失败")
}
}
type CharCount struct {
ch int
nm int
sc int
oc int
}
func test15() {
filename1 := "C:/Users/yzt/Desktop/test.txt"
file, err := os.Open(filename1)
if err != nil {
fmt.Println("open file err:", err)
return
}
defer file.Close()
var count CharCount
reader := bufio.NewReader(file)
for {
str, err := reader.ReadString('
')
if err == io.EOF {
break
}
str2 := []rune(str)
for _, v := range str2 {
switch {
case v >= 'a' && v <= 'z':
fallthrough
case 'A' <= v && v <= 'Z':
count.ch++
case v == ' ' || v == ' ':
count.sc++
case '0' <= v && v <= '9':
count.nm++
default:
count.oc++
}
}
}
fmt.Printf("字符的个数为=%v 数字的个数为=%v 空格的个数为=%v 其它字符个数=%v",
count.ch, count.nm, count.sc, count.oc)
}
func test16(args []string) {
/*
// 首个参数是当前文件路径, 之后为执行时后面接的参数
PS F:go_dev> go run day01/example1 1 2 3
命令行的参数有 4
C:UsersyztAppDataLocalTempgo-build1572730542001exeexample1.exe
1
2
3
*/
for _, v := range args {
fmt.Println(v)
}
}
func test17() {
var user string
var pwd string
var host string
var port int
/*
PS F:go_dev> go run day01/example1 -u alex -p 123456
命令行的参数有 5
alex 123456 localhost 3306
*/
flag.StringVar(&user, "u", "", "用户名, 默认为空")
flag.StringVar(&pwd, "p", "", "密码, 默认为空")
flag.StringVar(&host, "h", "localhost", "主机名, 默认为localhost")
flag.IntVar(&port, "port", 3306, "端口号默认为3306")
flag.Parse()
fmt.Println(user, pwd, host, port)
}
type Monster struct {
Name string `json:"name"`
Age int `json:"age"`
Birthday string `json:"birthday"`
Sal float64 `json:"slary"`
Skill string `json:"slill"`
}
func test18() {
// 序列化对象
moster := Monster{
Name: "牛魔王",
Age: 500,
Birthday: "2011-11-11",
Sal: 8000.0,
Skill: "牛崽子",
}
data, err := json.Marshal(&moster)
if err != nil {
fmt.Println("json序列化struct失败: err", err)
return
}
fmt.Println(string(data))
// 序列化字典
var a map[string]interface{}
a = make(map[string]interface{})
a["name"] = "红孩儿"
a["age"] = 30
a["address"] = "洪崖洞"
data, err = json.Marshal(&a)
if err != nil {
fmt.Println("json序列化map失败: err", err)
return
}
fmt.Println(string(data))
// 序列化切片
var slice []map[string]interface{}
var m1 map[string]interface{}
m1 = make(map[string]interface{})
m1["name"] = "红孩儿"
m1["age"] = 30
m1["address"] = "洪崖洞"
slice = append(slice, m1)
var m2 map[string]interface{}
m2 = make(map[string]interface{})
m2["name"] = "八戒"
m2["age"] = 3000
m2["address"] = "高老庄"
slice = append(slice, m2)
data, err = json.Marshal(&slice)
if err != nil {
fmt.Println("json序列化slice失败: err", err)
return
}
fmt.Println(string(data))
var num1 float32 = 2345.67
data, err = json.Marshal(&num1)
if err != nil {
fmt.Println("json序列化float32失败: err", err)
return
}
fmt.Println(string(data))
}
func test19() {
// 反序列化struct
str := "{"Name":"牛魔王","Age":500,"Birthday":"2011-11-11","Sal":8000,"Skill":"牛魔拳"}"
var monster Monster
err := json.Unmarshal([]byte(str), &monster)
if err != nil {
fmt.Println("反序列化struct失败: err", err)
return
}
fmt.Println(monster, monster.Name)
// 反序列换map
str = "{"address":"洪崖洞","age":30,"name":"红孩儿"}"
var a map[string]interface{}
err = json.Unmarshal([]byte(str), &a)
if err != nil {
fmt.Println("反序列化map失败: err", err)
return
}
fmt.Println(a, a["address"])
// 反序列化slice
str = "[{"address":"北京","age":"7","name":"jack"}," +
"{"address":["墨西哥","夏威夷"],"age":"20","name":"tom"}]"
var slice []map[string]interface{}
err = json.Unmarshal([]byte(str), &slice)
if err != nil {
fmt.Println("反序列化slice失败: err", err)
return
}
fmt.Println(slice, slice[0])
/*
对上面代码的小结说明
1) 在反序列化一个json字符串时,要确保反序列化后的数据类型和原来序列化前的数据类型一致。
2) 如果 json 字符串是通过程序获取到的,则不需要再对 “ 转义处理。
*/
}
func main() {
// test1() // 接口和继承
// test2() // 多态
// test3() // 类型断言
// test4() // 类型断言
// test5()
// test6() //文件操作os.File
// test7() // ioutil
// test8() // os.OpenFile 写入数据
// test9() // 打开一个存在的文件, 覆盖其中的数据
// test10() // 打开一个存在的文件, 向其中追加数据
// test11() // 打开一个存在的文件, 将其中内容输出控制台, 之后向其中追加数据
// test12() // 编程一个程序,将一个文件的内容,写入到另外一个文件。注:这两个文件已经存在了
// test13() // 判断文件是否存在
// test14() // 文件拷贝
// test15() // 统计英文、数字、空格和其他字符数量
fmt.Println("命令行的参数有", len(os.Args))
// test16(os.Args) // 命令行参数
// test17() // flag包解析命令行参数
test18() // json序列化
test19() // json反序列化
}