Golang-C1-3

作用域

完成mycat

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package main

import (
	"fmt"
	"io/ioutil"
)

func printFile(name string) {
	buf, err := ioutil.ReadFile(name)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(string(buf))
}

func main() {
	//补全缺失的代码完成cat命令
}

要求:程序放到个人的mycat目录下

判断如下程序的输出,并说明原因

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

import (
	"fmt"
)

var x = 200 //声明并初始化变量x 类型 int

func localFunc() {
	fmt.Println(x)
}

func main() {
	x := 1      //重新声明变量 x 影子变量
	localFunc() //函数内 变量x 取的是全局变量,并没有传参或者做指针引用;任何地方调用此函数 打印结果都是200
	if true {
		x := 100       //重新声明变量 x  影子变量
		fmt.Println(x) //if作用域内x为100
	}

	localFunc()
	fmt.Println(x) //打印的是此函数内同作用域的变量值 1

	// 打印结果:200 100 200 1
}

Go/Python使用的是词法作用域

mycat.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package main

import (
	"fmt"
	"io/ioutil"
	"os"
)

func readFile(name string) {
	buf, err := ioutil.ReadFile(name)
	if err != nil {
		fmt.Printf("%s\n", err.Error())
		return
	}
	fmt.Println(string(buf))
}

func main() {
	if len(os.Args) < 2 {
		fmt.Print("Please input filename")
	}
	//fileName := os.Args[1]
	//readFile(fileName)
	for i := 1; i < len(os.Args); i++ {
		readFile(os.Args[i])
	}
}

词法区域解析

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import "fmt"

var x = 200 //声明x是全局变量

func localFunc() {
	fmt.Println(x)
}

func main() {
	x := 1 //这里的x是main函数里的,局部变量

	localFunc()    //200,调用localFunc函数,里面的x引用的是全局变量var声明的200
	fmt.Println(x) //1,这里x是main函数声明的局部变量x的值1
	if true {
		x := 100       //这里又声明了x变量,只在if作用域有效
		fmt.Println(x) //100,这里的x是if作用域x的值100
	}

	localFunc()    //200,调用localFunc函数,还里x还是全局变量x的值没改200
	fmt.Println(x) //1,这里的x是main函数的x的值是1
}

整数

type.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main

import (
	"fmt"
	"unsafe"
)

func main() {
	var (
		x byte

		x1 int8

		x2 int32
		x3 int64
		x4 uint8
		x5 uint32
		x6 uint64
	)
	x4 = 255
	x4 = x4 + 1
	fmt.Println(x, x1, x2, x3, x4, x5, x6)
	fmt.Println(unsafe.Sizeof(x1))
}

字符串

str.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package main

import "fmt"

func main() {
	s1 := "hello" + "world"

	s2 := "helloworld"

	if s1 == s2 {
		fmt.Println("equal")
	}

	fmt.Println(0, len(s1)-1)

	var c1 byte
	c1 = s1[0]
	fmt.Println(s1, s2, c1)
	fmt.Printf("数字:%d 字符:%c\n", c1, c1)

	s3 := s1[:]
	fmt.Println(s3)

	var b byte
	for b = 0; b < 177; b++ {
		fmt.Printf("%d %c\n", b, b)
	}

	array := []byte(s1)
	fmt.Println(array)
	array[0] = 72 // 'H'
	s1 = string(array)
	fmt.Println(s1)

	fmt.Println('a' + ('H' - 'h'))

	fmt.Println(0xa)
	fmt.Println(toupper("hello"))
}

func toupper(s string) string {
	// len(s)
	// fmt.Println('a' + ('H' - 'h'))
	// array := []byte(s1)
	var result string
	return result
}

操作符与类型转换

布尔

  • 取值只有true和false
1
var b bool

bool.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package main

func main() {
	var b bool
	b = true
	b = false
	b = ("hello" == "world")
	if b {

	}
}

浮点数

1
fmt.Println(3/2)输出啥?

float.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package main

import "fmt"

func main() {
	var a, b int
	a = 10
	b = 3
	fmt.Println(a + b)
	fmt.Println(a - b)
	fmt.Println(a * b)
	fmt.Println(a / b)
	fmt.Println(a % b)
	a = a + 3 // a += 3
	if a >= b {

	}

	s := "hello"
	s += " world"

	if (a > b && b > 3) || b > 10 {

	}

	if (a == b) || (a != b) {

	}

	a = a * (b + 3)
}

常量

  • const关键字
  • 无明确类型

const.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main

import "fmt"

const (
	PI = 3.1415926
	E  = 2.0
	G  = 9.8
)

const (
	Hello = "hello"
)

const (
	A = iota
	B
	C
	D
)

func main() {
	fmt.Println(A, B, C)
}

强类型

  • 类型转换需要显式进行
  • 字符串跟数字需要借助函数转换strconv

cast.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package main

import (
	"fmt"
	"math/rand"
	"strconv"
	"time"
)

func main() {
	var n int
	var f float32
	n = 10
	f = float32(n) / 3
	fmt.Println(f * 3)
	n = int(f * 3)
	fmt.Println(f, n)

	var n1 int64
	n1 = 1024004
	var n2 int8
	n2 = int8(n1)
	fmt.Println(n1, n2)

	n1 = 1024129
	n2 = int8(n1)
	fmt.Println(n1, n2)

	var s string
	s = strconv.Itoa(n)
	fmt.Println(s)

	n, err := strconv.Atoi("123")
	if err != nil {
		fmt.Println("error", err)
	}

	fmt.Println(n)

	var x int64
	rand.Seed(time.Now().Unix())
	x = rand.Int63()
	s = strconv.FormatInt(x, 10)
	fmt.Println(s)
	//"世界上只有10种人,一种懂二进制,一种不懂二进制"
}

练习

编写计算器,调用形式如expr 1 + 2

if和for语句

1
2
3
4
5
6
7
8
var all int
for i := 1; i < len(os.Args); i++ {
	s, err := strconv.Atoi(os.Args[i])
	if err == nitl {
		all += s
	}
}
fmt.Println("all is ->", all)

if语句

1
2
3
4
5
6
var x bool
if x {
	fmt.Println("true")
} else {
	fmt.Println("false")
}
  • 没有小括号‘(’
  • 只能是bool表达式、数字,字符串之类的不行

if.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package main

import (
	"fmt"
	"strconv"
)

func main() {
	s := "abc123"
	n, err := strconv.Atoi(s)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(n)

	if n, err := strconv.Atoi(s); err == nil {
		fmt.Println(n)
	}

	if s == "1" {

	} else if s == "2" {

	} else if s == "3" {

	}

	switch s {
	case "1":
		fmt.Println("s=", "1")
	case "2":
		fmt.Println("s=", "2")

	default:
		fmt.Println("s=", "default", s)
	}
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package main

func main() {
	var s string
	if s == "" {
	
	} else if s == "21" {
	
	} else if s == "32" {
	
	}
}

if加判断语句

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
	"fmt"
	"strconv"
)

func main() {
	s := "abc123"
	n, err := strconv.Atoi(s)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(n)
	
	if n, err := strconv.Atoi(s); err == nil {
		fmt.Println(n)
	}
}

switch 语句

1
2
3
4
5
6
7
8
switch s {
	case "1":
			fmt.Println("s=", "1")
	case "2":
			fmt.Println("s=", "2")
	default:
			fmt.Println("s=", "default", s)
}

for循环1

1
2
3
for i := 0; i < 3; i++ {
	fmt.Println(i)
}
1
2
3
4
5
6
7
8
9
package main

import "fmt"

func main() {
	for i := 2; i < 3; i++ {
		fmt.Println(i)
	}
}

for循环3

1
2
3
4
5
6
7
8
9
i = 8
// 等丛刊于 while true
for {
	i = i + 1
	fmt.Println(i)
	if i > 10 {
		break
	}
}

for.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package main

import (
	"fmt"
	"os"
)

func main() {
	for i := 0; i < len(os.Args); i++ {
		fmt.Println(os.Args[i])
	}

	i := 5
	for i < 7 {
		fmt.Println(i)
		i = i + 1
	}

	i = 7
	for {
		if i > 10 {
			break
		}
		i = i + 1
	}

	for _, arg := range os.Args {
		fmt.Println(arg)
	}

	s := "hello中文"
	for i, arg := range s {
		fmt.Printf("%d %c\n", i, arg)
	}
}

switch.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package main

import (
	"fmt"
	"os"
)

func main() {
	m := 10
	n := 3
	switch os.Args[1] {
	case "+":
		fmt.Println(m + n)
	}
}

斐波那契数列

练习

输出100的斐波那契数之各

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import "fmt"
func main() {
	var sum int = 0
	var i1, i2 int = 0, 1
	for i2 < 100 (
		i1, i2 = i2, i1 + i2
		sum += i1
	)
	fmt.Println(sum)
}

文件读取和写入

打开关闭文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package main

import (
	"log"
	"os"
)

func main() {
	f, err := os.Create("a.txt")
	if err != nil {
		log.Fatal(err)
	}
	f.WriteString("hello\n")
	f.close()
}

写入文件

  • 顺序写入
  • 随机写入

open.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package main

import (
	"os"
	"log"
)

func main() {
	//f, err := os.OpenFile("a.txt", os.O_CREATE|os.O_RDWR, 0644)
	//f.Close()
	f, err := os.OpenFile("a.txt", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
	if err != nil {
		log.Fatal(err)
	}
	f.WriteString("hello\n")
	f.close()
}

godoc.org/os#pkg-constants

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package main

import (
	"os"
	"log"
)

func main() {
	f, err := os.OpenFile("a.txt", os.O_CREATE|os.O_RDWR, 0644)
	if err != nil {
		log.Fatal(err)
	}
	f.WriteString("hello\n")
	f.Seek(1, os.SEEK_SET)
	f.WriteString("$$")
	f.close()
}

读取文件

  • 顺序读取
  • 随机读取
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main

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

func main() {
	f, err := os.OpenFile("a.txt", os.O_CREATE|os.O_RDWR, 0644)
	if err != nil {
		log.Fatal(err)
	}
	
	r := bufio.NewReader(f)
	for {
		line, err := r.ReadString('\n')
		if err != io.EOF {
			break
		}
		fmt.Print(line)
	}
	f.Close()
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package main

import (

	"log"
	"os"
)

func main() {
	//f, err := os.OpenFile("a.txt", os.O_CREATE|os.O_RDWR, 0644)
	f, err := os.Open("a.txt")
	if err != nil {
		log.Fatal(err)
	}
	f.Seek(3, os.SEEK_SET)
	buf := make([]byte, 2)
	f.Read(buf)
	fmt.Println(string(buf))
	
	/*
	r := bufio.NewReader(f)
	for {
		line, err := r.ReadString('\n')
		if err != io.EOF {
			break
		}
		fmt.Print(line)
	}
	f.Close()
	*/
}

练习1

打印9x9乘法表,并写入到文件中

fmt.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
	"fmt"
	"log"
	"os"
)

func main() {
	f, err := os.Create("fmt.txt")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Fprint(f, "hello")
	fmt.Fprintln(f, "helloln")
	s := "hello"
	n := 4
	fmt.Fprintf(f, "my string is:%s n=%d\n", s, n)
	f.Close()
}

读取目录

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package main

import (
	"log"
	"os"
)

func main() {
	f, err := os.Open(".")
	if err != nil {
		log.Fatal(err)
	}
	infos, err := f.Readdir(-1)
	names, err := f.Readdirnames(-1)
}

ls.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
	"fmt"
	"log"
	"os"
)

func main() {
	f, err := os.Open(os.Args[1])
	if err != nil {
		log.Fatal(err)
	}
	infos, _ := f.Readdir(-1)
	for _, info := range infos {
		fmt.Printf("%v %d %s\n", info.IsDir(), info.Size(), info.Name())
	}
	f.Close()

}

homework

补全expr命令,支持+ - * /四个命令

要求:

  • myexpr 11 \* 2

注意:

  • *会被shell转义掉,使用\*代替

知识点:

  • switch知识
  • strconv

完成ps命令

要求:

  • 输出两列,类似1123 bash的结果

注意:

  • 使用pid/cmdline获取命令

翻转字符串