├── 0document ├── Go-command │ ├── 0.0.md │ ├── 0.1.md │ ├── 0.10.md │ ├── 0.11.md │ ├── 0.12.md │ ├── 0.13.md │ ├── 0.14.md │ ├── 0.2.md │ ├── 0.3.md │ ├── 0.4.md │ ├── 0.5.md │ ├── 0.6.md │ ├── 0.7.md │ ├── 0.8.md │ ├── 0.9.md │ ├── LICENSE │ ├── SUMMARY.md │ ├── goc2p │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── README.md │ │ └── src │ │ │ ├── basic │ │ │ ├── cgo │ │ │ │ ├── cgo_demo.go │ │ │ │ └── lib │ │ │ │ │ ├── go_export.go │ │ │ │ │ ├── go_export_def.go │ │ │ │ │ ├── math.go │ │ │ │ │ ├── print.go │ │ │ │ │ └── rand.go │ │ │ ├── map1 │ │ │ │ ├── cmap.go │ │ │ │ ├── cmap_test.go │ │ │ │ ├── common.go │ │ │ │ ├── keys.go │ │ │ │ ├── keys_test.go │ │ │ │ ├── omap.go │ │ │ │ └── omap_test.go │ │ │ ├── pkginit │ │ │ │ └── initpkg_demo.go │ │ │ ├── prof │ │ │ │ ├── profiling.go │ │ │ │ └── profiling_test.go │ │ │ ├── seq.go │ │ │ ├── set │ │ │ │ ├── hash_set.go │ │ │ │ ├── hash_set_test.go │ │ │ │ ├── set.go │ │ │ │ └── set_test.go │ │ │ ├── set2.go │ │ │ └── set2_test.go │ │ │ ├── chan1 │ │ │ └── oneway │ │ │ │ └── phandler.go │ │ │ ├── cnet │ │ │ └── ctcp │ │ │ │ ├── base.go │ │ │ │ ├── tcp.go │ │ │ │ └── tcp_test.go │ │ │ ├── helper │ │ │ ├── ds │ │ │ │ └── showds.go │ │ │ └── pds │ │ │ │ └── showpds.go │ │ │ ├── loadgen │ │ │ ├── gen.go │ │ │ ├── gen_test.go │ │ │ ├── lib │ │ │ │ ├── base.go │ │ │ │ ├── caller.go │ │ │ │ └── tickets.go │ │ │ ├── log.go │ │ │ └── testhelper │ │ │ │ ├── comm.go │ │ │ │ └── server.go │ │ │ ├── logging │ │ │ ├── base.go │ │ │ ├── console_logger.go │ │ │ ├── log_manager.go │ │ │ ├── logger_test.go │ │ │ └── tag.go │ │ │ ├── multiproc │ │ │ ├── apipe │ │ │ │ └── apipe.go │ │ │ ├── npipe │ │ │ │ └── npipe.go │ │ │ ├── signal │ │ │ │ └── mysignal.go │ │ │ └── socket │ │ │ │ └── tcpsock.go │ │ │ ├── pkgtool │ │ │ ├── envir.go │ │ │ ├── envir_test.go │ │ │ ├── fpath.go │ │ │ ├── ipath.go │ │ │ ├── pnode.go │ │ │ ├── util.go │ │ │ └── util_test.go │ │ │ ├── sync1 │ │ │ ├── datafile1 │ │ │ │ └── datafile1.go │ │ │ ├── datafile2 │ │ │ │ └── datafile2.go │ │ │ ├── datafile3 │ │ │ │ └── datafile3.go │ │ │ └── pool │ │ │ │ └── pool_demo.go │ │ │ ├── testing │ │ │ ├── bmt │ │ │ │ └── bmt_test.go │ │ │ ├── ct │ │ │ │ └── ct_demo.go │ │ │ ├── et │ │ │ │ └── et_test.go │ │ │ └── rp │ │ │ │ └── rp_test.go │ │ │ └── webcrawler │ │ │ ├── analyzer │ │ │ ├── analyzer.go │ │ │ ├── parser.go │ │ │ └── pool.go │ │ │ ├── base │ │ │ ├── argument.go │ │ │ ├── data.go │ │ │ ├── error.go │ │ │ └── logger.go │ │ │ ├── demo │ │ │ └── demo.go │ │ │ ├── downloader │ │ │ ├── downloader.go │ │ │ └── pool.go │ │ │ ├── itempipeline │ │ │ ├── pipeline.go │ │ │ └── processor.go │ │ │ ├── middleware │ │ │ ├── chanman.go │ │ │ ├── id.go │ │ │ ├── pool.go │ │ │ └── stopsign.go │ │ │ ├── scheduler │ │ │ ├── cache.go │ │ │ ├── helper.go │ │ │ ├── scheduler.go │ │ │ └── summary.go │ │ │ └── tool │ │ │ ├── cookie │ │ │ └── cookiejar.go │ │ │ └── monitor.go │ └── images │ │ ├── 0-1.jpg │ │ ├── 0-2.jpg │ │ ├── 0-3.jpg │ │ └── 0-4.jpg ├── Go笔记 ├── SHELL ├── SHELL-BASE │ ├── answerelif.sh │ ├── answerelif2.sh │ ├── answerif.sh │ ├── break.sh │ ├── breakcontcase.sh │ ├── case.sh │ ├── case1.sh │ ├── case2.sh │ ├── case3.sh │ ├── case4.sh │ ├── case5.sh │ ├── dot.sh │ ├── eval.sh │ ├── exists.sh │ ├── export.sh │ ├── find.txt │ ├── for.sh │ ├── for2.sh │ ├── for3.sh │ ├── forstring.sh │ ├── forstring1.sh │ ├── func.sh │ ├── func1.sh │ ├── getoptcp.sh │ ├── getoptdate.sh │ ├── grep.txt │ ├── if.sh │ ├── if2.sh │ ├── if3.sh │ ├── if4.sh │ ├── if5.sh │ ├── if6.sh │ ├── if7.sh │ ├── iscontinue.sh │ ├── maohao.sh │ ├── my_name.sh │ ├── qiuhe.sh │ ├── qiuhe2.sh │ ├── set.sh │ ├── shift.sh │ ├── shift1.sh │ ├── trap.sh │ ├── try_var.sh │ ├── unset.sh │ ├── until.sh │ ├── until1.sh │ ├── untilwho.sh │ ├── while.sh │ ├── while1.sh │ ├── whilepd.sh │ └── 杂项 ├── SHELL打印颜色 ├── SHELL特殊变量 ├── SHELL特殊用法 ├── diff-patch ├── git-cmd ├── linux-bin ├── linux-cmd ├── linux-firewall ├── mysql_backup.sh └── sublime快捷键 ├── 1Go语言 ├── Unicode.go ├── bitcomputing.go ├── bool.go ├── byte.go ├── complex.go ├── complex2.go ├── const.go ├── const2.go ├── const3.go ├── const4.go ├── const5.go ├── eq.go ├── eq1.go ├── float.go ├── globalvar.go ├── int.go ├── int2.go ├── iota.go ├── localvar.go ├── logic.go ├── math.go ├── pointer.go ├── relationship.go ├── string.go ├── string2.go ├── string3.go └── var.go ├── 2Go顺序结构程序 ├── 1.go ├── 10.go ├── 11.go ├── 12.go ├── 13.go ├── 14.go ├── 15.go ├── 16.go ├── 17.go ├── 18.go ├── 19.go ├── 2.go ├── 20.go ├── 21.go ├── 22.go ├── 23.go ├── 3.go ├── 4.go ├── 5.go ├── 6.go ├── 7.go ├── 8.go └── 9.go ├── 3Go选择结构程序 ├── 1.go ├── 10.go ├── 11.go ├── 12.go ├── 2.go ├── 3.go ├── 4.go ├── 5.go ├── 6.go ├── 7.go ├── 8.go └── 9.go ├── 4Go循环结构程序 ├── 1.go ├── 10.go ├── 11.go ├── 12.go ├── 2.go ├── 3.go ├── 4.go ├── 5.go ├── 6.go ├── 7.go ├── 8.go └── 9.go ├── 5数组切片和字典 ├── 1.go ├── 10.go ├── 11.go ├── 12.go ├── 13.go ├── 13bytes.go ├── 13newmake.go ├── 2.go ├── 3.go ├── 4.go ├── 5.go ├── 6.go ├── 7.go ├── 8.go └── 9.go ├── 6函数 ├── 1.go ├── 10.go ├── 11.go ├── 12.go ├── 13.go ├── 14.go ├── 15.go ├── 2.go ├── 3.go ├── 3parameter-passing.go ├── 4.go ├── 5.go ├── 6.go ├── 7.go ├── 8.go ├── 9.go ├── Go闭包.go └── mymath.go ├── 7结构体和方法 ├── 1.go ├── 10.go ├── 11.go ├── 12.go ├── 13.go ├── 14.go ├── 15.go ├── 16.go ├── 17.go ├── 18.go ├── 18mystruct.go ├── 19.go ├── 2.go ├── 3.go ├── 4.go ├── 5.go ├── 6.go ├── 7.go ├── 8.go ├── 9.go └── readme.md ├── 8接口 ├── 1.go ├── 2.go ├── 3.go ├── 4.go ├── 5.go ├── 6.go ├── 7.go └── 8.go ├── Go并发程序 ├── 1.go ├── 2.go ├── 3.go ├── 4.go ├── 5.go ├── 6.go ├── 7.go ├── 8.go └── 9.go ├── Go网络编程 ├── 1.go ├── 10.go ├── 11.go ├── 12.go ├── 13.go ├── 14.go ├── 15.go ├── 2.go ├── 3.go ├── 4.go ├── 5.go ├── 6.go ├── 7.go ├── 8.go └── 9.go ├── Go语言技巧 ├── a.import导入包 ├── b.main和init函数 ├── c.函数作为值和类型 ├── d.testing框架 ├── e.template模板 ├── f.gdb-golang ├── g.go反射规则 ├── h.go并发框架 ├── i.go-error ├── j.go通道 ├── k.go命令行 ├── l.go定时器 ├── m.go打点器 ├── n.go工作池 ├── o.go速率限制 ├── p.go原子计数器 ├── q.go-mutex ├── r.go状态协程 ├── s.go-URL解析 ├── t.SHA1-Base64 ├── u.go-time ├── v.go标准库 ├── w.go-pprof ├── x.go-cgo ├── y.go-web-api └── z.go-yacc-gen ├── readme.md └── x-project ├── docker ├── a.docker-client ├── b.dockerfile ├── c.data-volume ├── d.ssh-dockerfile ├── e.mysql-dockerfile ├── f.docker-network ├── g.container └── h.docker-server ├── etcd ├── etcd-API ├── etcd-base ├── etcd-cluster ├── etcd-config ├── etcd-framework ├── etcd-proxy.jpg ├── etcd-scenes.pdf ├── raft.pdf └── runtime-reconfig └── kubernetes ├── Borg.pdf ├── kubernetes-base ├── kubernetes-deploy ├── kubernetes-framework ├── kubernetes.jpg └── label.jpg /0document/Go-command/0.0.md: -------------------------------------------------------------------------------- 1 | # 标准命令详解 2 | 3 | Go语言的1.5版本在标准命令方面有了重大变更。这倒不是说它们的用法有多大的变化,而是说它们的底层支持已经大变样了。让我们先来对比一下`$GOROOT/pkg/tool/<平台相关目录>`中的内容。以下简称此目录为Go工具目录。 4 | 5 | **插播:**平台相关目录即以_命名的目录,用于存放因特定平台的不同而不同的代码包归档文件或可执行文件。其中,代表特定平台的操作系统代号,而则代表特定平台的计算架构代号。使用`go env`命令便可查看它们在你的计算机中的实际值。 6 | 7 | 1.4版本的Go工具目录的内容如下: 8 | 9 | ```bash 10 | 5a 5l 6g 8c addr2line dist objdump tour 11 | 5c 6a 6l 8g cgo fix pack vet 12 | 5g 6c 8a 8l cover nm pprof yacc 13 | ``` 14 | 15 | 下面是Go 1.5版本的: 16 | 17 | ```bash 18 | addr2line asm compile dist fix nm pack tour vet 19 | api cgo cover doc link objdump pprof trace yacc 20 | ``` 21 | 22 | 可以看到,1.5版本的目录内容精简了不少。这是因为Go 1.5的编译器、链接器都已经完全用Go语言重写了。而在这之前,它们都是用C语言写的,因此不得不为每类平台编写不同的程序并生成不同的文件。例如,8g、6g和5g分别是gc编译器在x86(32bit)、x86-64(64bit)和ARM计算架构的计算机上的实现程序。相比之下,用Go语言实现的好处就是,编译器和链接器都将是跨平台的了。简要来说,Go 1.5版本的目录中的文件compile即是统一后的编译器,而文件link则是统一后的链接器。 23 | 24 | 本教程并不会讲解Go语言的编译器、链接器以及其它工具是怎样被编写出来的,并只会关注于怎样用好包含它们在内的Go语言自带的命令和工具。 25 | 26 | 为了让讲解更具关联性,也为了让读者能够更容易的理解这些命令和工具,本教程并不会按照这些命令的字典顺序描述它们,而会按照我们在实际开发过程中通常的使用顺序以及它们的重要程度来逐一进行说明。现在,我们就先从`go build`命令开始。 27 | -------------------------------------------------------------------------------- /0document/Go-command/0.4.md: -------------------------------------------------------------------------------- 1 | # go clean 2 | 3 | 4 | 执行```go clean```命令会删除掉执行其它命令时产生的一些文件和目录,包括: 5 | 6 | 1. 在使用```go build```命令时在当前代码包下生成的与包名同名或者与Go源码文件同名的可执行文件。在Windows下,则是与包名同名或者Go源码文件同名且带有“.exe”后缀的文件。 7 | 8 | 2. 在执行```go test```命令并加入```-c```标记时在当前代码包下生成的以包名加“.test”后缀为名的文件。在Windows下,则是以包名加“.test.exe”后缀为名的文件。我们会在后面专门介绍```go test```命令。 9 | 10 | 3. 如果执行```go clean```命令时带有标记```-i```,则会同时删除安装(执行```go install```命令)当前代码包时所产生的结果文件。如果当前代码包中只包含库源码文件,则结果文件指的就是在工作区的pkg目录的相应目录下的归档文件。如果当前代码包中只包含一个命令源码文件,则结果文件指的就是在工作区的bin目录下的可执行文件。 11 | 12 | 4. 还有一些目录和文件是在编译Go或C源码文件时留在相应目录中的。包括:“_obj”和“_test”目录,名称为“_testmain.go”、“test.out”、“build.out”或“a.out”的文件,名称以“.5”、“.6”、“.8”、“.a”、“.o”或“.so”为后缀的文件。这些目录和文件是在执行```go build```命令时生成在临时目录中的。如果你忘记了这个临时目录是怎么回事儿,可以再回顾一下前面关于```go build```命令的介绍。临时目录的名称以```go-build```为前缀。 13 | 14 | 5. 如果执行```go clean```命令时带有标记```-r```,则还包括当前代码包的所有依赖包的上述目录和文件。 15 | 16 | 我们再以goc2p项目的```logging```为例。为了能够反复体现每个标记的作用,我们会使用标记```-n```。使用标记```-n```会让命令在执行过程中打印用到的系统命令,但不会真正执行它们。如果想既打印命令又执行命令则需使用标记```-x```。现在我们来试用一下```go clean```命令: 17 | 18 | hc@ubt:~/golang/goc2p/src$ go clean -x logging 19 | cd /home/hc/golang/goc2p/src/logging 20 | rm -f logging logging.exe logging.test logging.test.exe 21 | 22 | 现在,我们加上标记```-i```: 23 | 24 | hc@ubt:~/golang/goc2p/src$ go clean -x -i logging 25 | cd /home/hc/golang/goc2p/src/logging 26 | rm -f logging logging.exe logging.test logging.test.exe 27 | rm -f /home/hc/golang/goc2p/pkg/linux_386/logging.a 28 | 29 | 如果再加上标记```-r```又会打印出哪些命令呢?请读者自己试一试吧。 -------------------------------------------------------------------------------- /0document/Go-command/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Robert Hao 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | -------------------------------------------------------------------------------- /0document/Go-command/SUMMARY.md: -------------------------------------------------------------------------------- 1 | - [标准命令详解](0.0.md) 2 | - [go build](0.1.md) 3 | - [go install](0.2.md) 4 | - [go get](0.3.md) 5 | - [go clean](0.4.md) 6 | - [godoc](0.5.md) 7 | - [go run](0.6.md) 8 | - [go test](0.7.md) 9 | - [go list](0.8.md) 10 | - [go fmt与go tool fix](0.10.md) 11 | - [go vet与go tool vet](0.11.md) 12 | - [go tool pprof](0.12.md) 13 | - [go tool cgo](0.13.md) 14 | - [go env](0.14.md) 15 | - [Go语言并发编程实战中的代码](goc2p) 16 | - [pprof工具收集CPU 内存 Goroutine阻塞事件的函数封装](https://github.com/yaouser/GoUnix/tree/master/0document/Go-command/goc2p/src/basic/prof) 17 | - [网络爬虫的设计与实现](https://github.com/yaouser/GoUnix/tree/master/0document/Go-command/goc2p/src/webcrawler) 18 | 19 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/.gitignore: -------------------------------------------------------------------------------- 1 | bin**/* 2 | pkg**/* 3 | logs**/* 4 | pprof**/* 5 | _obj 6 | *.exe 7 | *.out 8 | *.di 9 | *.callgrind 10 | .DS_Store 11 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/README.md: -------------------------------------------------------------------------------- 1 | goc2p 2 | ===== 3 | 4 | Go Concurrency Programming Project. 5 | 6 | A example project for book 'Go Programming & Concurrency in Practice' (《Go并发编程实战》). 7 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/basic/cgo/cgo_demo.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | cgolib "basic/cgo/lib" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | input := float32(2.33) 10 | output, err := cgolib.Sqrt(input) 11 | if err != nil { 12 | fmt.Errorf("Error: %s\n", err) 13 | } 14 | fmt.Printf("The square root of %f is %f.\n", input, output) 15 | 16 | cgolib.Print("ABC\n") 17 | 18 | cgolib.CallCFunc() 19 | } 20 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/basic/cgo/lib/go_export.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | /* 4 | #include 5 | extern void CFunction1(); 6 | */ 7 | import "C" 8 | 9 | import "fmt" 10 | 11 | //export GoFunction1 12 | func GoFunction1() { 13 | fmt.Println("GoFunction1() is called.") 14 | } 15 | 16 | func CallCFunc() { 17 | C.CFunction1() 18 | } 19 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/basic/cgo/lib/go_export_def.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | /* 4 | #include 5 | void CFunction1() { 6 | printf("CFunction1() is called.\n"); 7 | GoFunction1(); 8 | } 9 | */ 10 | import "C" 11 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/basic/cgo/lib/math.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | /* 4 | #cgo LDFLAGS: -lm 5 | #include 6 | */ 7 | import "C" 8 | 9 | func Sqrt(p float32) (float32, error) { 10 | result, err := C.sqrt(C.double(p)) 11 | return float32(result), err 12 | } 13 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/basic/cgo/lib/print.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | /* 4 | #include 5 | #include 6 | 7 | void myprint(char* s) { 8 | printf("%s", s); 9 | } 10 | */ 11 | import "C" 12 | import "unsafe" 13 | 14 | func Print(s string) { 15 | cs := C.CString(s) 16 | defer C.free(unsafe.Pointer(cs)) 17 | C.myprint(cs) 18 | } 19 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/basic/cgo/lib/rand.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | /* 4 | #include 5 | */ 6 | import "C" 7 | 8 | func Random() int { 9 | return int(C.rand()) 10 | } 11 | 12 | func Seed(i int) { 13 | C.srand(C.uint(i)) 14 | } 15 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/basic/map1/common.go: -------------------------------------------------------------------------------- 1 | package map1 2 | 3 | import ( 4 | "reflect" 5 | ) 6 | 7 | // 泛化的Map的接口类型 8 | type GenericMap interface { 9 | // 获取给定键值对应的元素值。若没有对应元素值则返回nil。 10 | Get(key interface{}) interface{} 11 | // 添加键值对,并返回与给定键值对应的旧的元素值。若没有旧元素值则返回(nil, true)。 12 | Put(key interface{}, elem interface{}) (interface{}, bool) 13 | // 删除与给定键值对应的键值对,并返回旧的元素值。若没有旧元素值则返回nil。 14 | Remove(key interface{}) interface{} 15 | // 清除所有的键值对。 16 | Clear() 17 | // 获取键值对的数量。 18 | Len() int 19 | // 判断是否包含给定的键值。 20 | Contains(key interface{}) bool 21 | // 获取已排序的键值所组成的切片值。 22 | Keys() []interface{} 23 | // 获取已排序的元素值所组成的切片值。 24 | Elems() []interface{} 25 | // 获取已包含的键值对所组成的字典值。 26 | ToMap() map[interface{}]interface{} 27 | // 获取键的类型。 28 | KeyType() reflect.Type 29 | // 获取元素的类型。 30 | ElemType() reflect.Type 31 | } 32 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/basic/pkginit/initpkg_demo.go: -------------------------------------------------------------------------------- 1 | package main // 命令源码文件必须在这里声明自己属于main包 2 | 3 | import ( // 引入了代码包fmt和runtime 4 | "fmt" 5 | "runtime" 6 | ) 7 | 8 | func init() { // 包初始化函数 9 | fmt.Printf("Map: %v\n", m) // 先格式化再打印 10 | // 通过调用runtime包的代码获取当前机器所运行的操作系统以及计算架构 11 | // 而后通过fmt包的Sprintf方法进行字符串格式化并赋值给变量info 12 | info = fmt.Sprintf("OS: %s, Arch: %s", runtime.GOOS, runtime.GOARCH) 13 | } 14 | 15 | var m map[int]string = map[int]string{1: "A", 2: "B", 3: "C"} // 非局部变量,map类型,且已初始化 16 | 17 | var info string // 非局部变量,string类型,未被初始化 18 | 19 | func main() { // 命令源码文件必须有的入口函数 20 | fmt.Println(info) // 打印变量info 21 | } 22 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/basic/set/hash_set.go: -------------------------------------------------------------------------------- 1 | package set 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | ) 7 | 8 | type HashSet struct { 9 | m map[interface{}]bool 10 | } 11 | 12 | func NewHashSet() *HashSet { 13 | return &HashSet{m: make(map[interface{}]bool)} 14 | } 15 | 16 | func (set *HashSet) Add(e interface{}) bool { 17 | if !set.m[e] { 18 | set.m[e] = true 19 | return true 20 | } 21 | return false 22 | } 23 | 24 | func (set *HashSet) Remove(e interface{}) { 25 | delete(set.m, e) 26 | } 27 | 28 | func (set *HashSet) Clear() { 29 | set.m = make(map[interface{}]bool) 30 | } 31 | 32 | func (set *HashSet) Contains(e interface{}) bool { 33 | return set.m[e] 34 | } 35 | 36 | func (set *HashSet) Len() int { 37 | return len(set.m) 38 | } 39 | 40 | func (set *HashSet) Same(other Set) bool { 41 | if other == nil { 42 | return false 43 | } 44 | if set.Len() != other.Len() { 45 | return false 46 | } 47 | for key := range set.m { 48 | if !other.Contains(key) { 49 | return false 50 | } 51 | } 52 | return true 53 | } 54 | 55 | func (set *HashSet) Elements() []interface{} { 56 | initialLen := len(set.m) 57 | snapshot := make([]interface{}, initialLen) 58 | actualLen := 0 59 | for key := range set.m { 60 | if actualLen < initialLen { 61 | snapshot[actualLen] = key 62 | } else { 63 | snapshot = append(snapshot, key) 64 | } 65 | actualLen++ 66 | } 67 | if actualLen < initialLen { 68 | snapshot = snapshot[:actualLen] 69 | } 70 | return snapshot 71 | } 72 | 73 | func (set *HashSet) String() string { 74 | var buf bytes.Buffer 75 | buf.WriteString("HashSet{") 76 | first := true 77 | for key := range set.m { 78 | if first { 79 | first = false 80 | } else { 81 | buf.WriteString(" ") 82 | } 83 | buf.WriteString(fmt.Sprintf("%v", key)) 84 | } 85 | buf.WriteString("}") 86 | return buf.String() 87 | } 88 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/cnet/ctcp/base.go: -------------------------------------------------------------------------------- 1 | package ctcp 2 | 3 | import ( 4 | "net" 5 | "time" 6 | ) 7 | 8 | type TcpMessage struct { 9 | content string 10 | err error 11 | } 12 | 13 | func (self TcpMessage) Content() string { 14 | return self.content 15 | } 16 | 17 | func (self TcpMessage) Err() error { 18 | return self.err 19 | } 20 | 21 | func NewTcpMessage(content string, err error) TcpMessage { 22 | return TcpMessage{content: content, err: err} 23 | } 24 | 25 | type TcpListener interface { 26 | Init(addr string) error 27 | Listen(handler func(conn net.Conn)) error 28 | Close() bool 29 | Addr() net.Addr 30 | } 31 | 32 | type TcpSender interface { 33 | Init(remoteAddr string, timeout time.Duration) error 34 | Send(content string) error 35 | Receive(delim byte) <-chan TcpMessage 36 | Close() bool 37 | Addr() net.Addr 38 | RemoteAddr() net.Addr 39 | } 40 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/helper/ds/showds.go: -------------------------------------------------------------------------------- 1 | // Show the specified directory structure 2 | package main 3 | 4 | import ( 5 | "flag" 6 | "fmt" 7 | "os" 8 | "path" 9 | "strings" 10 | ) 11 | 12 | const ( 13 | INDENT = " " 14 | ) 15 | 16 | var ( 17 | rootPath string 18 | ) 19 | 20 | func init() { 21 | flag.StringVar(&rootPath, "p", "", "The path of target directory.") 22 | } 23 | 24 | func showFiles(basePath string, prefix string, showAll bool) error { 25 | base, err := os.Open(basePath) 26 | if err != nil { 27 | return err 28 | } 29 | subs, err := base.Readdir(-1) 30 | if err != nil { 31 | return err 32 | } 33 | for _, v := range subs { 34 | fi := v.(os.FileInfo) 35 | fp := fi.Name() 36 | if strings.HasPrefix(fp, ".") && !showAll { 37 | continue 38 | } 39 | if fi.IsDir() { 40 | absFp := path.Join(basePath, fp) 41 | if err != nil { 42 | return err 43 | } 44 | fmt.Printf("%s/\n", prefix+fp) 45 | err = showFiles(absFp, INDENT+prefix, showAll) 46 | if err != nil { 47 | return err 48 | } 49 | } else { 50 | fmt.Printf("%s\n", prefix+fp) 51 | } 52 | } 53 | return nil 54 | } 55 | 56 | func main() { 57 | flag.Parse() 58 | if len(rootPath) == 0 { 59 | defaultPath, err := os.Getwd() 60 | if err != nil { 61 | fmt.Println("GetwdError:", err) 62 | return 63 | } 64 | rootPath = defaultPath 65 | } 66 | fmt.Printf("%s:\n", rootPath) 67 | err := showFiles(rootPath, INDENT, false) 68 | if err != nil { 69 | fmt.Println("showFilesError:", err) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/helper/pds/showpds.go: -------------------------------------------------------------------------------- 1 | // Show the dependency structure of specified package 2 | package main 3 | 4 | import ( 5 | "basic/prof" 6 | "bytes" 7 | "errors" 8 | "flag" 9 | "fmt" 10 | "os" 11 | "pkgtool" 12 | "runtime/debug" 13 | "strings" 14 | ) 15 | 16 | const ( 17 | ARROWS = "->" 18 | ) 19 | 20 | var ( 21 | pkgImportPathFlag string 22 | ) 23 | 24 | func init() { 25 | flag.StringVar(&pkgImportPathFlag, "p", "", "The path of target package.") 26 | } 27 | 28 | func main() { 29 | prof.Start() 30 | defer func() { 31 | prof.Stop() 32 | if err := recover(); err != nil { 33 | fmt.Errorf("FATAL ERROR: %s", err) 34 | debug.PrintStack() 35 | } 36 | }() 37 | flag.Parse() 38 | pkgImportPath := getPkgImportPath() 39 | pn := pkgtool.NewPkgNode(pkgImportPath) 40 | fmt.Printf("The package node of '%s': %v\n", pkgImportPath, *pn) 41 | err := pn.Grow() 42 | if err != nil { 43 | fmt.Printf("GROW ERROR: %s\n", err) 44 | } 45 | fmt.Printf("The dependency structure of package '%s':\n", pkgImportPath) 46 | ShowDepStruct(pn, "") 47 | } 48 | 49 | func ShowDepStruct(pnode *pkgtool.PkgNode, prefix string) { 50 | var buf bytes.Buffer 51 | buf.WriteString(prefix) 52 | importPath := pnode.ImportPath() 53 | buf.WriteString(importPath) 54 | deps := pnode.Deps() 55 | //fmt.Printf("P_NODE: '%s', DEP_LEN: %d\n", importPath, len(deps)) 56 | if len(deps) == 0 { 57 | fmt.Printf("%s\n", buf.String()) 58 | return 59 | } 60 | buf.WriteString(ARROWS) 61 | for _, v := range deps { 62 | ShowDepStruct(v, buf.String()) 63 | } 64 | } 65 | 66 | func getPkgImportPath() string { 67 | if len(pkgImportPathFlag) > 0 { 68 | return pkgImportPathFlag 69 | } 70 | fmt.Printf("The flag p is invalid, use current dir as package import path.") 71 | currentDir, err := os.Getwd() 72 | if err != nil { 73 | panic(err) 74 | } 75 | srcDirs := pkgtool.GetSrcDirs(false) 76 | var importPath string 77 | for _, v := range srcDirs { 78 | if strings.HasPrefix(currentDir, v) { 79 | importPath = currentDir[len(v):] 80 | break 81 | } 82 | } 83 | if strings.TrimSpace(importPath) == "" { 84 | panic(errors.New("Can not parse the import path!")) 85 | } 86 | return importPath 87 | } 88 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/loadgen/lib/base.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // 原生请求的结构。 8 | type RawReq struct { 9 | Id int64 10 | Req []byte 11 | } 12 | 13 | // 原生响应的结构。 14 | type RawResp struct { 15 | Id int64 16 | Resp []byte 17 | Err error 18 | Elapse time.Duration 19 | } 20 | 21 | type ResultCode int 22 | 23 | // 保留 1 ~ 1000 给载荷承受者使用。 24 | const ( 25 | RESULT_CODE_SUCCESS = 0 // 成功。 26 | RESULT_CODE_WARNING_CALL_TIMEOUT ResultCode = 1001 // 调用超时警告。 27 | RESULT_CODE_ERROR_CALL ResultCode = 2001 // 调用错误。 28 | RESULT_CODE_ERROR_RESPONSE ResultCode = 2002 // 响应内容错误。 29 | RESULT_CODE_ERROR_CALEE ResultCode = 2003 // 被调用方(被测软件)的内部错误。 30 | RESULT_CODE_FATAL_CALL ResultCode = 3001 // 调用过程中发生了致命错误! 31 | ) 32 | 33 | func GetResultCodePlain(code ResultCode) string { 34 | var codePlain string 35 | switch code { 36 | case RESULT_CODE_SUCCESS: 37 | codePlain = "Success" 38 | case RESULT_CODE_WARNING_CALL_TIMEOUT: 39 | codePlain = "Call Timeout Warning" 40 | case RESULT_CODE_ERROR_CALL: 41 | codePlain = "Call Error" 42 | case RESULT_CODE_ERROR_RESPONSE: 43 | codePlain = "Response Error" 44 | case RESULT_CODE_ERROR_CALEE: 45 | codePlain = "Callee Error" 46 | case RESULT_CODE_FATAL_CALL: 47 | codePlain = "Call Fatal Error" 48 | default: 49 | codePlain = "Unknown result code" 50 | } 51 | return codePlain 52 | } 53 | 54 | // 调用结果的结构。 55 | type CallResult struct { 56 | Id int64 // ID。 57 | Req RawReq // 原生请求。 58 | Resp RawResp // 原生响应。 59 | Code ResultCode // 响应代码。 60 | Msg string // 结果成因的简述。 61 | Elapse time.Duration // 耗时。 62 | } 63 | 64 | // 载荷发生器的状态的类型。 65 | type GenStatus int 66 | 67 | const ( 68 | STATUS_ORIGINAL GenStatus = 0 69 | STATUS_STARTED GenStatus = 1 70 | STATUS_STOPPED GenStatus = 2 71 | ) 72 | 73 | // 载荷发生器的接口。 74 | type Generator interface { 75 | // 启动载荷发生器。 76 | Start() 77 | // 停止载荷发生器。 78 | // 第一个结果值代表已发载荷总数,且仅在第二个结果值为true时有效。 79 | // 第二个结果值代表是否成功将载荷发生器转变为已停止状态。 80 | Stop() (uint64, bool) 81 | // 获取状态。 82 | Status() GenStatus 83 | } 84 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/loadgen/lib/caller.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // 调用器的接口。 8 | type Caller interface { 9 | // 构建请求。 10 | BuildReq() RawReq 11 | // 调用。 12 | Call(req []byte, timeoutNs time.Duration) ([]byte, error) 13 | // 检查响应。 14 | CheckResp(rawReq RawReq, rawResp RawResp) *CallResult 15 | } 16 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/loadgen/lib/tickets.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | // Goroutine票池的接口。 9 | type GoTickets interface { 10 | // 拿走一张票。 11 | Take() 12 | // 归还一张票。 13 | Return() 14 | // 票池是否已被激活。 15 | Active() bool 16 | // 票的总数。 17 | Total() uint32 18 | // 剩余的票数。 19 | Remainder() uint32 20 | } 21 | 22 | // Goroutine票池的实现。 23 | type myGoTickets struct { 24 | total uint32 // 票的总数。 25 | ticketCh chan byte // 票的容器。 26 | active bool // 票池是否已被激活。 27 | } 28 | 29 | func NewGoTickets(total uint32) (GoTickets, error) { 30 | gt := myGoTickets{} 31 | if !gt.init(total) { 32 | errMsg := 33 | fmt.Sprintf("The goroutine ticket pool can NOT be initialized! (total=%d)\n", total) 34 | return nil, errors.New(errMsg) 35 | } 36 | return >, nil 37 | } 38 | 39 | func (gt *myGoTickets) init(total uint32) bool { 40 | if gt.active { 41 | return false 42 | } 43 | if total == 0 { 44 | return false 45 | } 46 | ch := make(chan byte, total) 47 | n := int(total) 48 | for i := 0; i < n; i++ { 49 | ch <- 1 50 | } 51 | gt.ticketCh = ch 52 | gt.total = total 53 | gt.active = true 54 | return true 55 | } 56 | 57 | func (gt *myGoTickets) Take() { 58 | <-gt.ticketCh 59 | } 60 | 61 | func (gt *myGoTickets) Return() { 62 | gt.ticketCh <- 1 63 | } 64 | 65 | func (gt *myGoTickets) Active() bool { 66 | return gt.active 67 | } 68 | 69 | func (gt *myGoTickets) Total() uint32 { 70 | return gt.total 71 | } 72 | 73 | func (gt *myGoTickets) Remainder() uint32 { 74 | return uint32(len(gt.ticketCh)) 75 | } 76 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/loadgen/log.go: -------------------------------------------------------------------------------- 1 | package loadgen 2 | 3 | import ( 4 | "logging" 5 | ) 6 | 7 | var logger logging.Logger 8 | 9 | func init() { 10 | logger = logging.NewSimpleLogger() 11 | } 12 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/logging/tag.go: -------------------------------------------------------------------------------- 1 | package logging 2 | 3 | const ( 4 | ERROR_LOG_KEY = "ERROR" 5 | FATAL_LOG_KEY = "FATAL" 6 | INFO_LOG_KEY = "INFO" 7 | PANIC_LOG_KEY = "PANIC" 8 | WARN_LOG_KEY = "WARN" 9 | ) 10 | 11 | type LogTag struct { 12 | name string 13 | prefix string 14 | } 15 | 16 | func (self *LogTag) Name() string { 17 | return self.name 18 | } 19 | 20 | func (self *LogTag) Prefix() string { 21 | return self.prefix 22 | } 23 | 24 | var logTagMap map[string]LogTag = map[string]LogTag{ 25 | ERROR_LOG_KEY: LogTag{name: ERROR_LOG_KEY, prefix: "[" + ERROR_LOG_KEY + "]"}, 26 | FATAL_LOG_KEY: LogTag{name: FATAL_LOG_KEY, prefix: "[" + FATAL_LOG_KEY + "]"}, 27 | INFO_LOG_KEY: LogTag{name: INFO_LOG_KEY, prefix: "[" + INFO_LOG_KEY + "]"}, 28 | PANIC_LOG_KEY: LogTag{name: PANIC_LOG_KEY, prefix: "[" + PANIC_LOG_KEY + "]"}, 29 | WARN_LOG_KEY: LogTag{name: WARN_LOG_KEY, prefix: "[" + WARN_LOG_KEY + "]"}, 30 | } 31 | 32 | func getErrorLogTag() LogTag { 33 | return logTagMap[ERROR_LOG_KEY] 34 | } 35 | 36 | func getFatalLogTag() LogTag { 37 | return logTagMap[FATAL_LOG_KEY] 38 | } 39 | 40 | func getInfoLogTag() LogTag { 41 | return logTagMap[INFO_LOG_KEY] 42 | } 43 | 44 | func getPanicLogTag() LogTag { 45 | return logTagMap[PANIC_LOG_KEY] 46 | } 47 | 48 | func getWarnLogTag() LogTag { 49 | return logTagMap[WARN_LOG_KEY] 50 | } 51 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/multiproc/npipe/npipe.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | "time" 8 | ) 9 | 10 | func main() { 11 | fileBasedPipe() 12 | inMemorySyncPipe() 13 | } 14 | 15 | func fileBasedPipe() { 16 | reader, writer, err := os.Pipe() 17 | if err != nil { 18 | fmt.Printf("Error: Can not create the named pipe: %s\n", err) 19 | } 20 | go func() { 21 | output := make([]byte, 100) 22 | n, err := reader.Read(output) 23 | if err != nil { 24 | fmt.Printf("Error: Can not read data from the named pipe: %s\n", err) 25 | } 26 | fmt.Printf("Read %d byte(s). [file-based pipe]\n", n) 27 | }() 28 | input := make([]byte, 26) 29 | for i := 65; i <= 90; i++ { 30 | input[i-65] = byte(i) 31 | } 32 | n, err := writer.Write(input) 33 | if err != nil { 34 | fmt.Printf("Error: Can not write data to the named pipe: %s\n", err) 35 | } 36 | fmt.Printf("Written %d byte(s). [file-based pipe]\n", n) 37 | time.Sleep(200 * time.Millisecond) 38 | } 39 | 40 | func inMemorySyncPipe() { 41 | reader, writer := io.Pipe() 42 | go func() { 43 | output := make([]byte, 100) 44 | n, err := reader.Read(output) 45 | if err != nil { 46 | fmt.Printf("Error: Can not read data from the named pipe: %s\n", err) 47 | } 48 | fmt.Printf("Read %d byte(s). [in-memory pipe]\n", n) 49 | }() 50 | input := make([]byte, 26) 51 | for i := 65; i <= 90; i++ { 52 | input[i-65] = byte(i) 53 | } 54 | n, err := writer.Write(input) 55 | if err != nil { 56 | fmt.Printf("Error: Can not write data to the named pipe: %s\n", err) 57 | } 58 | fmt.Printf("Written %d byte(s). [in-memory pipe]\n", n) 59 | time.Sleep(200 * time.Millisecond) 60 | } 61 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/pkgtool/envir.go: -------------------------------------------------------------------------------- 1 | package pkgtool 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "runtime" 7 | "strings" 8 | ) 9 | 10 | var srcDirsCache []string 11 | 12 | func init() { 13 | srcDirsCache = GetSrcDirs(true) 14 | } 15 | 16 | func GetGoroot() string { 17 | return runtime.GOROOT() 18 | } 19 | 20 | func GetAllGopath() []string { 21 | gopath := os.Getenv("GOPATH") 22 | var sep string 23 | if runtime.GOOS == "windows" { 24 | sep = ";" 25 | } else { 26 | sep = ":" 27 | } 28 | gopaths := strings.Split(gopath, sep) 29 | result := make([]string, 0) 30 | for _, v := range gopaths { 31 | if strings.TrimSpace(v) != "" { 32 | result = append(result, v) 33 | } 34 | } 35 | return result 36 | } 37 | 38 | func GetSrcDirs(fresh bool) []string { 39 | if len(srcDirsCache) > 0 && !fresh { 40 | return srcDirsCache 41 | } 42 | gorootSrcDir := filepath.Join(GetGoroot(), "src", "pkg") 43 | gopaths := GetAllGopath() 44 | gopathSrcDirs := make([]string, len(gopaths)) 45 | for i, v := range gopaths { 46 | gopathSrcDirs[i] = filepath.Join(v, "src") 47 | } 48 | srcDirs := make([]string, 0) 49 | srcDirs = append(srcDirs, gorootSrcDir) 50 | srcDirs = append(srcDirs, gopathSrcDirs...) 51 | srcDirsCache = make([]string, len(srcDirs)) 52 | copy(srcDirsCache, srcDirs) 53 | return srcDirs 54 | } 55 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/pkgtool/fpath.go: -------------------------------------------------------------------------------- 1 | package pkgtool 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "strings" 7 | ) 8 | 9 | func getAbsPathOfPackage(importPath string) string { 10 | for _, srcDir := range GetSrcDirs(false) { 11 | absPath := filepath.Join(srcDir, filepath.FromSlash(importPath)) 12 | //fmt.Printf("IP: %s, IP_DIR: %s, AP: %s\n", importPath, filepath.FromSlash(importPath), absPath) 13 | _, err := os.Open(absPath) 14 | if err == nil { 15 | return absPath 16 | } 17 | } 18 | return "" 19 | } 20 | 21 | func getGoSourceFileAbsPaths(packageAbspath string, containsTestFile bool) ([]string, error) { 22 | f, err := os.Open(packageAbspath) 23 | if err != nil { 24 | return nil, err 25 | } 26 | subs, err := f.Readdir(-1) 27 | if err != nil { 28 | return nil, err 29 | } 30 | absPaths := make([]string, 0) 31 | for _, v := range subs { 32 | fi := v.(os.FileInfo) 33 | name := fi.Name() 34 | if !fi.IsDir() && strings.HasSuffix(name, ".go") { 35 | if strings.HasSuffix(name, "_test.go") && !containsTestFile { 36 | continue 37 | } 38 | absPath := filepath.Join(packageAbspath, name) 39 | absPaths = append(absPaths, absPath) 40 | } 41 | } 42 | return absPaths, nil 43 | } 44 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/pkgtool/util.go: -------------------------------------------------------------------------------- 1 | package pkgtool 2 | 3 | func appendIfAbsent(s []string, t ...string) []string { 4 | for _, t1 := range t { 5 | var contains bool 6 | for _, s1 := range s { 7 | if s1 == t1 { 8 | contains = true 9 | break 10 | } 11 | } 12 | if !contains { 13 | s = append(s, t1) 14 | } 15 | } 16 | return s 17 | } 18 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/pkgtool/util_test.go: -------------------------------------------------------------------------------- 1 | package pkgtool 2 | 3 | import ( 4 | "runtime/debug" 5 | "testing" 6 | ) 7 | 8 | func TestAppendIfAbsent(t *testing.T) { 9 | t.Parallel() 10 | defer func() { 11 | if err := recover(); err != nil { 12 | debug.PrintStack() 13 | t.Errorf("Fatal Error: %s\n", err) 14 | } 15 | }() 16 | s := make([]string, 0) 17 | e1 := "a" 18 | s = appendIfAbsent(s, e1) 19 | expLen := 1 20 | actLen := len(s) 21 | if actLen != expLen { 22 | t.Errorf("Error: The length of slice should be %d but %d.\n", expLen, actLen) 23 | } 24 | if !contains(s, e1) { 25 | t.Errorf("Error: The slice should contains '%s' but not.\n", e1) 26 | } 27 | s = appendIfAbsent(s, e1) 28 | expLen = 1 29 | actLen = len(s) 30 | if actLen != expLen { 31 | t.Errorf("Error: The length of slice should be %d but %d.\n", expLen, actLen) 32 | } 33 | e2 := "b" 34 | s = appendIfAbsent(s, e2) 35 | expLen = 2 36 | actLen = len(s) 37 | if actLen != expLen { 38 | t.Errorf("Error: The length of slice should be %d but %d.\n", expLen, actLen) 39 | } 40 | expS := []string{"a", "b"} 41 | if !sliceEquels(s, expS) { 42 | t.Errorf("Error: The slice should be %v but %v.\n", expS, s) 43 | } 44 | } 45 | 46 | func contains(s []string, e string) bool { 47 | for _, v := range s { 48 | if v == e { 49 | return true 50 | } 51 | } 52 | return false 53 | } 54 | 55 | func sliceEquels(s1 []string, s2 []string) bool { 56 | if len(s1) != len(s2) { 57 | return false 58 | } 59 | for i, v1 := range s1 { 60 | v2 := s2[i] 61 | if v1 != v2 { 62 | return false 63 | } 64 | } 65 | return true 66 | } 67 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/sync1/pool/pool_demo.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | "runtime/debug" 7 | "sync" 8 | "sync/atomic" 9 | ) 10 | 11 | func main() { 12 | // 禁用GC,并保证在main函数执行结束前恢复GC 13 | defer debug.SetGCPercent(debug.SetGCPercent(-1)) 14 | var count int32 15 | newFunc := func() interface{} { 16 | return atomic.AddInt32(&count, 1) 17 | } 18 | pool := sync.Pool{New: newFunc} 19 | 20 | // New 字段值的作用 21 | v1 := pool.Get() 22 | fmt.Printf("v1: %v\n", v1) 23 | 24 | // 临时对象池的存取 25 | pool.Put(newFunc()) 26 | pool.Put(newFunc()) 27 | pool.Put(newFunc()) 28 | v2 := pool.Get() 29 | fmt.Printf("v2: %v\n", v2) 30 | 31 | // 垃圾回收对临时对象池的影响 32 | debug.SetGCPercent(100) 33 | runtime.GC() 34 | v3 := pool.Get() 35 | fmt.Printf("v3: %v\n", v3) 36 | pool.New = nil 37 | v4 := pool.Get() 38 | fmt.Printf("v4: %v\n", v4) 39 | } 40 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/testing/bmt/bmt_test.go: -------------------------------------------------------------------------------- 1 | package bmt 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | ) 7 | 8 | func Benchmark(b *testing.B) { 9 | customTimerTag := false 10 | if customTimerTag { 11 | b.StopTimer() 12 | } 13 | b.SetBytes(12345678) 14 | time.Sleep(time.Second) 15 | if customTimerTag { 16 | b.StartTimer() 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/testing/ct/ct_demo.go: -------------------------------------------------------------------------------- 1 | package ct 2 | 3 | func TypeCategoryOf(v interface{}) string { 4 | switch v.(type) { 5 | case bool: 6 | return "boolean" 7 | case int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64: 8 | return "integer" 9 | case float32, float64: 10 | return "float" 11 | case complex64, complex128: 12 | return "complex" 13 | case string: 14 | a := "string" 15 | return a 16 | } 17 | return "unknown" 18 | } 19 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/testing/et/et_test.go: -------------------------------------------------------------------------------- 1 | package et 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func ExampleHello() { 9 | for i := 0; i < 3; i++ { 10 | fmt.Println("Hello, Golang~") 11 | } 12 | 13 | // Output: Hello, Golang~ 14 | // Hello, Golang~ 15 | // Hello, Golang~ 16 | } 17 | 18 | func TestOne(t *testing.T) { 19 | t.Log("Hi~") 20 | } 21 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/testing/rp/rp_test.go: -------------------------------------------------------------------------------- 1 | package rp 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func BenchmarkParallel(b *testing.B) { 9 | b.SetParallelism(3) 10 | fmt.Printf("\nN: %d\n", b.N) 11 | var index int 12 | b.RunParallel(func(pb *testing.PB) { 13 | i := index 14 | index++ 15 | var count int 16 | for pb.Next() { 17 | count++ 18 | } 19 | fmt.Printf("count[%d]: %d \n", i, count) 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/webcrawler/analyzer/parser.go: -------------------------------------------------------------------------------- 1 | package analyzer 2 | 3 | import ( 4 | "net/http" 5 | base "webcrawler/base" 6 | ) 7 | 8 | // 被用于解析HTTP响应的函数类型。 9 | type ParseResponse func(httpResp *http.Response, respDepth uint32) ([]base.Data, []error) 10 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/webcrawler/analyzer/pool.go: -------------------------------------------------------------------------------- 1 | package analyzer 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "reflect" 7 | mdw "webcrawler/middleware" 8 | ) 9 | 10 | // 生成分析器的函数类型。 11 | type GenAnalyzer func() Analyzer 12 | 13 | // 分析器池的接口类型。 14 | type AnalyzerPool interface { 15 | Take() (Analyzer, error) // 从池中取出一个分析器。 16 | Return(analyzer Analyzer) error // 把一个分析器归还给池。 17 | Total() uint32 // 获得池的总容量。 18 | Used() uint32 // 获得正在被使用的分析器的数量。 19 | } 20 | 21 | func NewAnalyzerPool( 22 | total uint32, 23 | gen GenAnalyzer) (AnalyzerPool, error) { 24 | etype := reflect.TypeOf(gen()) 25 | genEntity := func() mdw.Entity { 26 | return gen() 27 | } 28 | pool, err := mdw.NewPool(total, etype, genEntity) 29 | if err != nil { 30 | return nil, err 31 | } 32 | dlpool := &myAnalyzerPool{pool: pool, etype: etype} 33 | return dlpool, nil 34 | } 35 | 36 | type myAnalyzerPool struct { 37 | pool mdw.Pool // 实体池。 38 | etype reflect.Type // 池内实体的类型。 39 | } 40 | 41 | func (spdpool *myAnalyzerPool) Take() (Analyzer, error) { 42 | entity, err := spdpool.pool.Take() 43 | if err != nil { 44 | return nil, err 45 | } 46 | analyzer, ok := entity.(Analyzer) 47 | if !ok { 48 | errMsg := fmt.Sprintf("The type of entity is NOT %s!\n", spdpool.etype) 49 | panic(errors.New(errMsg)) 50 | } 51 | return analyzer, nil 52 | } 53 | 54 | func (spdpool *myAnalyzerPool) Return(analyzer Analyzer) error { 55 | return spdpool.pool.Return(analyzer) 56 | } 57 | 58 | func (spdpool *myAnalyzerPool) Total() uint32 { 59 | return spdpool.pool.Total() 60 | } 61 | func (spdpool *myAnalyzerPool) Used() uint32 { 62 | return spdpool.pool.Used() 63 | } 64 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/webcrawler/base/data.go: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | // 数据的接口。 8 | type Data interface { 9 | Valid() bool // 数据是否有效。 10 | } 11 | 12 | // 请求。 13 | type Request struct { 14 | httpReq *http.Request // HTTP请求的指针值。 15 | depth uint32 // 请求的深度。 16 | } 17 | 18 | // 创建新的请求。 19 | func NewRequest(httpReq *http.Request, depth uint32) *Request { 20 | return &Request{httpReq: httpReq, depth: depth} 21 | } 22 | 23 | // 获取HTTP请求。 24 | func (req *Request) HttpReq() *http.Request { 25 | return req.httpReq 26 | } 27 | 28 | // 获取深度值。 29 | func (req *Request) Depth() uint32 { 30 | return req.depth 31 | } 32 | 33 | // 数据是否有效。 34 | func (req *Request) Valid() bool { 35 | return req.httpReq != nil && req.httpReq.URL != nil 36 | } 37 | 38 | // 响应。 39 | type Response struct { 40 | httpResp *http.Response 41 | depth uint32 42 | } 43 | 44 | // 创建新的响应。 45 | func NewResponse(httpResp *http.Response, depth uint32) *Response { 46 | return &Response{httpResp: httpResp, depth: depth} 47 | } 48 | 49 | // 获取HTTP响应。 50 | func (resp *Response) HttpResp() *http.Response { 51 | return resp.httpResp 52 | } 53 | 54 | // 获取深度值。 55 | func (resp *Response) Depth() uint32 { 56 | return resp.depth 57 | } 58 | 59 | // 数据是否有效。 60 | func (resp *Response) Valid() bool { 61 | return resp.httpResp != nil && resp.httpResp.Body != nil 62 | } 63 | 64 | // 条目。 65 | type Item map[string]interface{} 66 | 67 | // 数据是否有效。 68 | func (item Item) Valid() bool { 69 | return item != nil 70 | } 71 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/webcrawler/base/error.go: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | ) 7 | 8 | // 错误类型。 9 | type ErrorType string 10 | 11 | // 错误类型常量。 12 | const ( 13 | DOWNLOADER_ERROR ErrorType = "Downloader Error" 14 | ANALYZER_ERROR ErrorType = "Analyzer Error" 15 | ITEM_PROCESSOR_ERROR ErrorType = "Item Processor Error" 16 | ) 17 | 18 | // 爬虫错误的接口。 19 | type CrawlerError interface { 20 | Type() ErrorType // 获得错误类型。 21 | Error() string // 获得错误提示信息。 22 | } 23 | 24 | // 爬虫错误的实现。 25 | type myCrawlerError struct { 26 | errType ErrorType // 错误类型。 27 | errMsg string // 错误提示信息。 28 | fullErrMsg string // 完整的错误提示信息。 29 | } 30 | 31 | // 创建一个新的爬虫错误。 32 | func NewCrawlerError(errType ErrorType, errMsg string) CrawlerError { 33 | return &myCrawlerError{errType: errType, errMsg: errMsg} 34 | } 35 | 36 | // 获得错误类型。 37 | func (ce *myCrawlerError) Type() ErrorType { 38 | return ce.errType 39 | } 40 | 41 | // 获得错误提示信息。 42 | func (ce *myCrawlerError) Error() string { 43 | if ce.fullErrMsg == "" { 44 | ce.genFullErrMsg() 45 | } 46 | return ce.fullErrMsg 47 | } 48 | 49 | // 生成错误提示信息,并给相应的字段赋值。 50 | func (ce *myCrawlerError) genFullErrMsg() { 51 | var buffer bytes.Buffer 52 | buffer.WriteString("Crawler Error: ") 53 | if ce.errType != "" { 54 | buffer.WriteString(string(ce.errType)) 55 | buffer.WriteString(": ") 56 | } 57 | buffer.WriteString(ce.errMsg) 58 | ce.fullErrMsg = fmt.Sprintf("%s\n", buffer.String()) 59 | return 60 | } 61 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/webcrawler/base/logger.go: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | import "logging" 4 | 5 | // 创建日志记录器。 6 | func NewLogger() logging.Logger { 7 | return logging.NewSimpleLogger() 8 | } 9 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/webcrawler/downloader/downloader.go: -------------------------------------------------------------------------------- 1 | package downloader 2 | 3 | import ( 4 | "logging" 5 | "net/http" 6 | base "webcrawler/base" 7 | mdw "webcrawler/middleware" 8 | ) 9 | 10 | // 日志记录器。 11 | var logger logging.Logger = base.NewLogger() 12 | 13 | // ID生成器。 14 | var downloaderIdGenerator mdw.IdGenerator = mdw.NewIdGenerator() 15 | 16 | // 生成并返回ID。 17 | func genDownloaderId() uint32 { 18 | return downloaderIdGenerator.GetUint32() 19 | } 20 | 21 | // 网页下载器的接口类型。 22 | type PageDownloader interface { 23 | Id() uint32 // 获得ID。 24 | Download(req base.Request) (*base.Response, error) // 根据请求下载网页并返回响应。 25 | } 26 | 27 | // 创建网页下载器。 28 | func NewPageDownloader(client *http.Client) PageDownloader { 29 | id := genDownloaderId() 30 | if client == nil { 31 | client = &http.Client{} 32 | } 33 | return &myPageDownloader{ 34 | id: id, 35 | httpClient: *client, 36 | } 37 | } 38 | 39 | // 网页下载器的实现类型。 40 | type myPageDownloader struct { 41 | id uint32 // ID。 42 | httpClient http.Client // HTTP客户端。 43 | } 44 | 45 | func (dl *myPageDownloader) Id() uint32 { 46 | return dl.id 47 | } 48 | 49 | func (dl *myPageDownloader) Download(req base.Request) (*base.Response, error) { 50 | httpReq := req.HttpReq() 51 | logger.Infof("Do the request (url=%s)... \n", httpReq.URL) 52 | httpResp, err := dl.httpClient.Do(httpReq) 53 | if err != nil { 54 | return nil, err 55 | } 56 | return base.NewResponse(httpResp, req.Depth()), nil 57 | } 58 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/webcrawler/downloader/pool.go: -------------------------------------------------------------------------------- 1 | package downloader 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "reflect" 7 | mdw "webcrawler/middleware" 8 | ) 9 | 10 | // 生成网页下载器的函数类型。 11 | type GenPageDownloader func() PageDownloader 12 | 13 | // 网页下载器池的接口类型。 14 | type PageDownloaderPool interface { 15 | Take() (PageDownloader, error) // 从池中取出一个网页下载器。 16 | Return(dl PageDownloader) error // 把一个网页下载器归还给池。 17 | Total() uint32 // 获得池的总容量。 18 | Used() uint32 // 获得正在被使用的网页下载器的数量。 19 | } 20 | 21 | // 创建网页下载器池。 22 | func NewPageDownloaderPool( 23 | total uint32, 24 | gen GenPageDownloader) (PageDownloaderPool, error) { 25 | etype := reflect.TypeOf(gen()) 26 | genEntity := func() mdw.Entity { 27 | return gen() 28 | } 29 | pool, err := mdw.NewPool(total, etype, genEntity) 30 | if err != nil { 31 | return nil, err 32 | } 33 | dlpool := &myDownloaderPool{pool: pool, etype: etype} 34 | return dlpool, nil 35 | } 36 | 37 | // 网页下载器池的实现类型。 38 | type myDownloaderPool struct { 39 | pool mdw.Pool // 实体池。 40 | etype reflect.Type // 池内实体的类型。 41 | } 42 | 43 | func (dlpool *myDownloaderPool) Take() (PageDownloader, error) { 44 | entity, err := dlpool.pool.Take() 45 | if err != nil { 46 | return nil, err 47 | } 48 | dl, ok := entity.(PageDownloader) 49 | if !ok { 50 | errMsg := fmt.Sprintf("The type of entity is NOT %s!\n", dlpool.etype) 51 | panic(errors.New(errMsg)) 52 | } 53 | return dl, nil 54 | } 55 | 56 | func (dlpool *myDownloaderPool) Return(dl PageDownloader) error { 57 | return dlpool.pool.Return(dl) 58 | } 59 | 60 | func (dlpool *myDownloaderPool) Total() uint32 { 61 | return dlpool.pool.Total() 62 | } 63 | func (dlpool *myDownloaderPool) Used() uint32 { 64 | return dlpool.pool.Used() 65 | } 66 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/webcrawler/itempipeline/processor.go: -------------------------------------------------------------------------------- 1 | package itemproc 2 | 3 | import ( 4 | base "webcrawler/base" 5 | ) 6 | 7 | // 被用来处理条目的函数类型。 8 | type ProcessItem func(item base.Item) (result base.Item, err error) 9 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/webcrawler/middleware/id.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "math" 5 | "sync" 6 | ) 7 | 8 | // ID生成器的接口类型。 9 | type IdGenerator interface { 10 | GetUint32() uint32 // 获得一个uint32类型的ID。 11 | } 12 | 13 | // 创建ID生成器。 14 | func NewIdGenerator() IdGenerator { 15 | return &cyclicIdGenerator{} 16 | } 17 | 18 | // ID生成器的实现类型。 19 | type cyclicIdGenerator struct { 20 | sn uint32 // 当前的ID。 21 | ended bool // 前一个ID是否已经为其类型所能表示的最大值。 22 | mutex sync.Mutex // 互斥锁。 23 | } 24 | 25 | func (gen *cyclicIdGenerator) GetUint32() uint32 { 26 | gen.mutex.Lock() 27 | defer gen.mutex.Unlock() 28 | if gen.ended { 29 | defer func() { gen.ended = false }() 30 | gen.sn = 0 31 | return gen.sn 32 | } 33 | id := gen.sn 34 | if id < math.MaxUint32 { 35 | gen.sn++ 36 | } else { 37 | gen.ended = true 38 | } 39 | return id 40 | } 41 | 42 | // ID生成器的接口类型2。 43 | type IdGenerator2 interface { 44 | GetUint64() uint64 // 获得一个uint64类型的ID。 45 | } 46 | 47 | // 创建ID生成器2。 48 | func NewIdGenerator2() IdGenerator2 { 49 | return &cyclicIdGenerator2{} 50 | } 51 | 52 | // ID生成器的实现类型2。 53 | type cyclicIdGenerator2 struct { 54 | base cyclicIdGenerator // 基本的ID生成器。 55 | cycleCount uint64 // 基于uint32类型的取值范围的周期计数。 56 | } 57 | 58 | func (gen *cyclicIdGenerator2) GetUint64() uint64 { 59 | var id64 uint64 60 | if gen.cycleCount%2 == 1 { 61 | id64 += math.MaxUint32 62 | } 63 | id32 := gen.base.GetUint32() 64 | if id32 == math.MaxUint32 { 65 | gen.cycleCount++ 66 | } 67 | id64 += uint64(id32) 68 | return id64 69 | } 70 | -------------------------------------------------------------------------------- /0document/Go-command/goc2p/src/webcrawler/tool/cookie/cookiejar.go: -------------------------------------------------------------------------------- 1 | package cookie 2 | 3 | import ( 4 | "code.google.com/p/go.net/publicsuffix" 5 | "net/http" 6 | "net/http/cookiejar" 7 | ) 8 | 9 | // 创建 http.CookieJar 类型的值。 10 | func NewCookiejar() http.CookieJar { 11 | options := &cookiejar.Options{PublicSuffixList: &myPublicSuffixList{}} 12 | cj, _ := cookiejar.New(options) 13 | return cj 14 | } 15 | 16 | // cookiejar.PublicSuffixList 接口的实现类型。 17 | type myPublicSuffixList struct{} 18 | 19 | func (psl *myPublicSuffixList) PublicSuffix(domain string) string { 20 | suffix, _ := publicsuffix.PublicSuffix(domain) 21 | return suffix 22 | } 23 | 24 | func (psl *myPublicSuffixList) String() string { 25 | return "Web crawler - public suffix list (rev 1.0) power by 'code.google.com/p/go.net/publicsuffix'" 26 | } 27 | -------------------------------------------------------------------------------- /0document/Go-command/images/0-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaouser/GoUnix/139f9e7778938c22e222743427952ee9056585d9/0document/Go-command/images/0-1.jpg -------------------------------------------------------------------------------- /0document/Go-command/images/0-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaouser/GoUnix/139f9e7778938c22e222743427952ee9056585d9/0document/Go-command/images/0-2.jpg -------------------------------------------------------------------------------- /0document/Go-command/images/0-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaouser/GoUnix/139f9e7778938c22e222743427952ee9056585d9/0document/Go-command/images/0-3.jpg -------------------------------------------------------------------------------- /0document/Go-command/images/0-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaouser/GoUnix/139f9e7778938c22e222743427952ee9056585d9/0document/Go-command/images/0-4.jpg -------------------------------------------------------------------------------- /0document/SHELL-BASE/answerelif.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Is it morning? Please answer yes or no" 4 | read timeofday 5 | 6 | if [ $timeofday = "yes" ] 7 | then 8 | echo "Good morning" 9 | elif [ $timeofday = "no" ] 10 | then 11 | echo "Good afternoon" 12 | else 13 | echo "Sorry, $timeofday not recognized, Enter yes or no" 14 | exit 1 15 | fi 16 | 17 | exit 0 18 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/answerelif2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #为了防止if语句中出现timeofday为空字符时,应将变量加双引号。 3 | echo -n "Is it morning? Please enter yes or no: " #使用-n选项时去掉每一行后面的换行符 4 | read timeofday 5 | 6 | if [ "$timeofday" = "yes" ] 7 | then 8 | echo "Good morning" 9 | elif [ "$timeofday" = "no" ] 10 | then 11 | echo "Good afternoon" 12 | else 13 | echo "Sorry, a not recognized. Enter yes or no" 14 | exit 1 15 | fi 16 | 17 | exit 0 18 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/answerif.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Is it morning? Please answer yes or no" 4 | read timeofday 5 | 6 | if [ $timeofday = "yes" ] 7 | then 8 | echo "Good morning" 9 | else 10 | echo "Good afternoon" 11 | fi 12 | 13 | exit 0 14 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/break.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #你可以用这个命令在控制条件未满足之前,跳出for while或until循环。你可以为break 3 | #命令提供一个额外的数值参数来表明需要跳出的循环层数,但我们并不建议读者这么做,因为 4 | #它将大大降低程序的可读性。在默认情况下,break只跳出一层循环。 5 | 6 | rm -rf fred* 7 | echo > fred1 8 | echo > fred2 9 | mkdir fred3 10 | echo > fred4 11 | 12 | for file in fred* 13 | do 14 | if [ -d "$file" ];then 15 | break; 16 | fi 17 | done 18 | 19 | echo first directory starting fred was $file 20 | rm -rf fred* 21 | 22 | exit 0 23 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/breakcontcase.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #Interactive program to restore, backup, or unload 3 | #a directory 4 | echo "Welcome to the menu driven Archive program" 5 | while true 6 | do 7 | #Display a Menu 8 | echo 9 | echo "Make a Choice from the Menu below" 10 | echo _ 11 | echo "1 Restore Archive" 12 | echo "2 Backup directory" 13 | echo "3 Unload directory" 14 | echo "4 Quit" 15 | echo 16 | 17 | # Read the user's selection 18 | echo -n "Enter Choice: " 19 | read CHOICE 20 | case $CHOICE in 21 | [1-3]) echo 22 | #Read and validate the name of the directory 23 | echo -n "What directory do you want?" 24 | read WORKDIR 25 | if [ ! -d "$WORKDIR" ] 26 | then 27 | echo "Sorry, $WORKDIR is not a directory" 28 | continue 29 | fi 30 | #Make the directory the current working directory 31 | cd $WORKDIR;; 32 | 4) : ;; # : is null,not excute everything 33 | *) echo "Sorry, $CHOICE is not a valid choice" 34 | continue 35 | esac 36 | 37 | case "$CHOICE" in 38 | 1) echo "Restoring..." 39 | cpio -i /dev/myfile/0h;; 42 | 3) echo "Unloading..." 43 | ls | cpio -o >/dev/myfile/0h;; 44 | 4) echo "Quitting" 45 | break;; 46 | esac 47 | 48 | #Check for cpio errors 49 | if [ $? -ne 0 ] 50 | then 51 | echo "A problem has occurred during the process" 52 | if [ $CHOICE = 3 ] 53 | then 54 | echo "The directory will not be erased" 55 | fi 56 | echo "Please check the device and try again" 57 | continue 58 | else 59 | if [ $CHOICE = 3 ] 60 | then 61 | ls -l #rm * 62 | fi 63 | fi 64 | done 65 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/case.sh: -------------------------------------------------------------------------------- 1 | case "$1" in 2 | start) 3 | start;; 4 | stop) 5 | stop;; 6 | status) 7 | rhstatus;; 8 | rstart|reload) 9 | restart;; 10 | condrestart) 11 | [ -f /var/lock/subsys/syslog ] && restart || : ;; 12 | *) 13 | echo "Usage:$0{start|stop|status|restart|condrestart}" 14 | exit 1 15 | esac 16 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/case1.sh: -------------------------------------------------------------------------------- 1 | #Display a menu 2 | echo _ 3 | echo "1 Restore" 4 | echo "2 Backup" 5 | echo "3 Unload" 6 | echo 7 | 8 | #Read and excute the user's selection 9 | echo -n "Enter Choice:" 10 | read CHOICE 11 | 12 | case "$CHOICE" in 13 | 1) echo "Restore";; 14 | 2) echo "Backup";; 15 | 3) echo "Unload";; 16 | *) echo "Sorry $CHOICE is not valid choice" 17 | exit 1;; 18 | esac 19 | 20 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/case2.sh: -------------------------------------------------------------------------------- 1 | #Display a menu 2 | echo _ 3 | echo "1 Restore" 4 | echo "2 Backup" 5 | echo "3 Unload" 6 | echo 7 | 8 | #Read and excute the user's selection 9 | echo -n "Enter Choice:" 10 | read CHOICE 11 | 12 | case "$CHOICE" in 13 | 1|R) echo "Restore";; 14 | 2|B) echo "Backup";; 15 | 3|U) echo "Unload";; 16 | *) echo "Sorry $CHOICE is not valid choice" 17 | exit 1;; 18 | esac 19 | 20 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/case3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #请注意,每个模式行都以双分号(;;)结尾。因为你可以在前后模式之间放置多条语句, 3 | #所以需要使用一个双分号来标记前一个语句的结束和后一个模式的开始。 4 | 5 | echo "Is it morning? Please answer yes or no" 6 | read timeofday 7 | 8 | case "$timeofday" in 9 | yes) echo "Good Morning";; 10 | no ) echo "Good Afternoon";; 11 | y ) echo "Good Morning";; 12 | n ) echo "Good Morning";; 13 | * ) echo "Sorry, answer not recognized";; 14 | esac 15 | 16 | exit 0 17 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/case4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Is it morning? Please answer yes or no" 4 | read timeofday 5 | 6 | case "$timeofday" in 7 | yes | y | Yes | YES ) echo "Good Morning";; 8 | n* | N* ) echo "Good Afternoon";; 9 | * ) echo "Sorry, answer not recognized";; 10 | esac 11 | 12 | exit 0 13 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/case5.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #最后,为了让这个脚本程序具备可重用性,你需要在使用默认模式时给出 3 | #另外一个退出码。 4 | 5 | echo "Is it morning? Please answer yes or no" 6 | read timeofday 7 | 8 | case "$timeofday" in 9 | yes | y | Yes | YES |[Yy][Ee][Ss]) 10 | echo "Good Morning" 11 | echo "Up bright and early this morning" 12 | ;; 13 | [nN]* ) 14 | echo "Good Afternoon" 15 | ;; 16 | * ) 17 | echo "Sorry, answer not recognized" 18 | echo "Please answer yes or no" 19 | exit 1 20 | ;; 21 | esac 22 | 23 | exit 0 24 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/dot.sh: -------------------------------------------------------------------------------- 1 | #通常,当一个脚本执行一条外部命令或脚本程序时,它会创建一个新的环境(一个子shell), 2 | #命令在这个新环境中执行,在命令执行完毕后,这个环境被丢弃,留下退出码返回给父shell。 3 | #但外部的source命令和点命令(这两个命令差不多是同义词)在执行脚本程序中列出的命令 4 | #时,使用的是调用该脚本程序的同一个shell。因为在默认情况下,shell脚本程序会在一个 5 | #新创建的环境中执行,所以脚本程序对环境变量所作的任何修改都会丢失。而点命令允许执行 6 | #的脚本程序改变当前环境。当你要把一个脚本当作“包裹器”来为后续执行的一些其他命令设置 7 | #环境时,这个命令通常就很有用。 8 | 9 | #!/bin/bash 10 | #第一个文件 11 | 12 | version=classic 13 | PATH=/usr/local/old_bin:/usr/bin:/bin:. 14 | PS1="classic> " 15 | 16 | #!/bin/bash 17 | #第二个文件 18 | 19 | version=latest 20 | PATH=/usr/local/new_bin:/usr/bin:/bin:. 21 | PS1=" latest version> " 22 | 23 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/eval.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | foo=10 4 | x=foo 5 | eval y='$'$x 6 | echo $y 7 | 8 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/exists.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -f /bin/bash ] 4 | then 5 | echo "file /bin/bash existes" 6 | fi 7 | 8 | if [ -d /bin/bash ] 9 | then 10 | echo "/bin/bash is a directory" 11 | else 12 | echo "/bin/bash is NOT a directory" 13 | fi 14 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/export.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #export命令将作为它参数的变量导出到子shell中,并使之在子shell中有效。 3 | #从更技术的角度来说,被导出的变量构成从该shell衍生的任何子进程的环境变量。 4 | 5 | #第一个文件 6 | 7 | echo "$foo" 8 | echo "$bar" 9 | 10 | #!/bin/bash 11 | 12 | #第二个文件 13 | 14 | foo="The first meta-syntactic variable" 15 | export bar="The second meta-syntactic variable" 16 | 17 | export2 18 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/find.txt: -------------------------------------------------------------------------------- 1 | find / -name test -print 2 | 3 | 这个命令的含义是:从根目录开始查找名为test的文件,并且输出该文件的完整路径。 4 | 但是较浪费时间,因为搜索了Linux机器挂载的其他文件系统(如SAMBA)。 5 | 6 | find / -mount -name test -print 7 | 8 | 如果指定-mount选项,你就可以告诉find命令不要搜索挂载的其他文件系统的目录。 9 | 10 | find命令的完整语法格式如下所示: 11 | find [path] [options] [tests] [actions] 12 | path部分很容易理解:你既可以使用绝对路径,如/bin,也可以使用相对路径,如.。 13 | 如果需要,也可以指定多个路径,如find /var /home。 14 | 一些主要的选项: 15 | -depth 在查看目录本身之前先搜索目录的内容 16 | -follow 跟随符号链接 17 | -maxdepths N 最多搜索N层目录 18 | -mount(或-xdev) 不搜索其他文件系统中的目录 19 | 由于圆括号对shell来说有其特殊的含义,所以你还必须使用反斜线来引用圆括号。 20 | 如: \(-newer X -o -name "_*" \) 21 | 含义:搜索的文件比文件X要新,或者文件名以下划线开头。 22 | find . -newer while2 -type f -print 23 | 在当前目录下搜索比文件while2要新的文件,在测试这个文件是否是一个普通文件 24 | (-type -f)。最后,使用-print来确认搜索到的文件。 25 | 26 | find . \( -name "_*" -or newer while2 \) -type f -print 27 | 28 | 下面来看看在发现匹配指定条件的文件之后,你可以执行的动作。 29 | 30 | -exec和-ok命令将命令行上后续的参数作为它们参数的一部分,直到被\;序列终止。 31 | 实际上,-exec和-ok命令执行的是一个嵌入式命令,所以嵌入式命令必须以一个转义 32 | 的分号结束,使得find命令可以决定什么时候它可以继续查找用于它自己的命令行选项。 33 | 魔术字符串{}是-exec或-ok命令的一个特殊类型的参数,它将被当前文件的完整路径 34 | 取代。 35 | -exec和-ok命令类似,只不过-ok在执行命令之前会针对每个要处理的文件,提示用户 36 | 进行确认。 37 | 38 | find . -newer while2 -type f -exec ls -l {} \; 39 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/for.sh: -------------------------------------------------------------------------------- 1 | for var in one two three four five 2 | do 3 | echo ---------- 4 | echo '$var is '$var 5 | echo 6 | done 7 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/for2.sh: -------------------------------------------------------------------------------- 1 | for ((i=1;i<=10;i++)) 2 | do 3 | echo "num is $i" 4 | done 5 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/for3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | for i in * 3 | do 4 | if [ -f $i ] 5 | then 6 | echo "$i is a file" 7 | elif [ -d $i ] 8 | then 9 | echo "$i is a directory" 10 | fi 11 | done 12 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/forstring.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for foo in bar fud 43 4 | do 5 | echo $foo 6 | done 7 | 8 | exit 0 9 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/forstring1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for file in $(ls f*.sh) 4 | do 5 | lpr $file #打印文件名 6 | done 7 | 8 | exit 0 9 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/func.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | foo() { 4 | echo "Function foo is executing" 5 | } 6 | 7 | echo "script starting" 8 | foo 9 | echo "script ended" 10 | 11 | exit 0 12 | 13 | #你必须在调用函数之前定义一个你需要的函数 14 | #也就是说,定义函数在前,调用函数在后。 15 | #这样才能正确执行。 16 | 17 | #当一个函数被调用时,脚本程序的位置参数($* $@ $1 $2等)会被替换为函数的 18 | #参数。这也是你读取传递给函数的参数的办法。当函数执行完毕后,这些参数会 19 | #恢复为它们先前的值。但移植性不强可用另外的方法: 20 | #foo(){echo JAY;} 21 | #... 22 | #result="$(foo)" 23 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/func1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #可用local在函数中声明局部变量,局部变量将仅在函数的作用范围内有效。 3 | #此外,函数可以访问全局作用范围内的其他shell变量。如果一个局部变量和 4 | #一个全局变量的名字相同,前者就会覆盖后者,但仅限于函数的作用范围之内。 5 | sample_text="global variale" 6 | foo(){ 7 | local sample_text="local variable" 8 | echo "Function foo is executing" 9 | echo $sample_text 10 | } 11 | 12 | echo "script starting" 13 | echo $sample_text 14 | 15 | foo 16 | 17 | echo "script ended" 18 | echo $sample_text 19 | 20 | exit 0 21 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/getoptcp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #Syntax: getoptcp [-c integer] [-v] filename 3 | #where integer is the number of duplicatecopies 4 | #and -v is the verbose option 5 | 6 | COPIES=1 7 | VERBOSE=N 8 | 9 | while getopt vc: OPTION 10 | do 11 | case $OPTION in 12 | c) COPIES=$OPTARG;; 13 | v) VERBOSE=Y;; 14 | \?) echo "illegal Option" 15 | exit 1;; 16 | esac 17 | done 18 | 19 | if [ $OPTIND -gt $# ] 20 | then 21 | echo "No file name specified" 22 | exit 2 23 | fi 24 | 25 | shift `expr $OPTIND - 1` 26 | 27 | FILE=$1 28 | COPY=0 29 | 30 | while [ $COPIES -gt $COPY ] 31 | do 32 | COPY=`expr 33 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/getoptdate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #NO SUCCUSS 3 | #filename: newdate 4 | if [ $# -lt 1 ] 5 | then 6 | date 7 | else 8 | while getopt mdyDHMSTjJwahr OPTION 9 | do 10 | case $OPTION 11 | in 12 | m)date '+%m';; #Month of Year 13 | d)date '+%d';; #Day of Month 14 | y)date '+%y';; #Year 15 | D)date '+%D';; #MM/DD/YY 16 | H)date '+%H';; #Hour 17 | M)date '+%M';; #Minute 18 | S)date '+%S';; #Second 19 | T)date '+%T';; #HH:MM:SS 20 | j)date '+%j';; #day of year 21 | J)date '+%y%j';; #digit Julian date 22 | w)date '+%w';; #Day of the Week 23 | a)date '%a';; #Day abbreviation 24 | h)date '+%h';; #Month abbreviation 25 | r)date '+%r';; #AM-PM time 26 | \?)echo "Invalid option $OPTION";; 27 | esac 28 | done 29 | fi 30 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/grep.txt: -------------------------------------------------------------------------------- 1 | 通用正则表达式解析器(General Regular Expression Parser,简写为grep)。 2 | 使用find命令在系统中搜索文件,而使用grep命令在文件中搜索字符串。事实上, 3 | 一种非常常见的用法是find命令时,将grep作为传递给-exec的一条命令。 4 | grep语法如下: 5 | grep [options] PATTERN [FILES] 6 | 一些重要的选项: 7 | -c 输出匹配行的数目。 8 | -E 启用扩展表达式。 9 | -h 取消每个输出行的普通前缀,即匹配查询模式的文件名。 10 | -i 忽略大小写。 11 | -l 只列出包含匹配行的文件名,而不输出真正的匹配行。 12 | -v 对匹配模式取反。 13 | 14 | 15 | 正则表达式 16 | 17 | ^ 指向一行的开头 18 | $ 指向一行的结尾 19 | . 任意单个字符 20 | [] 方括号内包含一个字符范围,其中任何一个字符都可以被匹配,或在字符范围前面 21 | 加上^符号表示反向字符范围,即不匹配指定范围内的字符。 22 | 23 | 在方括号中还可以使用一些有用的特殊匹配模式 24 | 25 | [:alnum:] 字母与数字符 26 | [:alpha:] 字母 27 | [:ascii:] ASCII字符 28 | [:blank:] 空格或制表符 29 | [:cntrl:] ASCII控制字符 30 | [:digit:] 数字 31 | [:graph:] 非控制 非空格字符 32 | [:lower:] 小写字母 33 | [:print:] 可打印字符 34 | [:punct:] 标点符号字符 35 | [:space:] 空白字符,包括垂直制表符 36 | [:upper:] 大写字母 37 | [:xdigit:] 十六进制数字 38 | 39 | 另外,如果指定了用于扩展匹配的-E选项,那些用于控制匹配完成的其他字符可能会 40 | 遵循正则表达式的规则(如下),对于grep命令来说,我们还需要在这些字符之前 41 | 加上\字符。 42 | 43 | ? 匹配是可选的,但最多匹配一次 44 | * 必须匹配0次或多次 45 | + 必须匹配1次或多次 46 | {n} 必须匹配n次 47 | {n,} 必须匹配n次或n次以上 48 | {n,m} 匹配次数在n到m之间,包括n和m 49 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/if.sh: -------------------------------------------------------------------------------- 1 | QQ(){ 2 | echo -n "Do you want to continue?(Yes/No):" 3 | read YN 4 | if echo "$YN" | grep -q '^[Yy]\([Ee][Ss]\)*$' 5 | QQ 6 | then 7 | exit 0 8 | fi 9 | } 10 | QQ 11 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/if2.sh: -------------------------------------------------------------------------------- 1 | QQ(){ 2 | echo -n "Do you want to continue?(Yes/No):" 3 | read YN 4 | case "$YN" in 5 | [Yy]|[Yy][Es][Ss]) 6 | QQ;; 7 | *) 8 | exit 0;; 9 | esac 10 | } 11 | QQ 12 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/if3.sh: -------------------------------------------------------------------------------- 1 | echo -n "Do you want to continue: Y or N" 2 | read ANSWER 3 | if [ $ANSWER=N -o $ANSWER=n ] 4 | then 5 | exit 6 | fi 7 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/if4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #所有的条件必须被满足才会被执行 3 | if [ -f this_file ]; then 4 | if [ -f that_file ]; then 5 | if [ -f the_other_file ]; then 6 | echo "All files present, and correct" 7 | fi 8 | fi 9 | fi 10 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/if5.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #希望至少在这一系列条件中有一个为真。 3 | 4 | if [ -f this_file ];then 5 | foo="True" 6 | elif [ -f that_file ];then 7 | foo="True" 8 | elif [ -f the_other_file ];then 9 | foo="True" 10 | else 11 | foo="False" 12 | fi 13 | 14 | if [ "$foo" = "True" ];then 15 | echo "One of the files exists" 16 | fi 17 | 18 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/if6.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | touch file_one 4 | rm -f file_two 5 | 6 | if [ -f file_one ] && echo "hello" && [ -f file_two ] && echo " there" 7 | then 8 | echo "in if" 9 | else 10 | echo "in else" 11 | fi 12 | 13 | exit 0 14 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/if7.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm -f file_one 4 | if [ -f file_one ] || echo "hello" || echo " there" 5 | then 6 | echo "in if" 7 | else 8 | echo "in else" 9 | fi 10 | 11 | exit 0 12 | 13 | #[ -f file_one ] && command for true || command for false 14 | #在上面的语句中,如果测试成功就会执行第一条命令,否则执行第二条命令。 15 | 16 | #如果你想在某些只允许使用单个语句的地方(比如在AND或OR列表中)使用多条语句,你 17 | #可以把它们括在花括号{}中来构造一个语句块。 18 | #get_confirm && { 19 | # grep -v "$cdcatnum" $tracks_file > $temp_file 20 | # cat $temp_file > $tracks_file 21 | # echo 22 | # add_record_tracks 23 | # } 24 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/iscontinue.sh: -------------------------------------------------------------------------------- 1 | iscontinue(){ 2 | while true 3 | do 4 | echo -n "Continue?(Y/N)" 5 | read ANSWER 6 | case $ANSWER in 7 | [Yy]) return 0;; 8 | [Nn]) return 1;; 9 | *) echo "Answer Y or N";; 10 | esac 11 | done 12 | } 13 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/maohao.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #冒号(:)命令是一个空命令。它偶尔会被用于简化条件逻辑,相当与true的一个别名。 3 | #由于它的内置命令,所以它运行的比true块,但它的输出可读性较差。 4 | #你可能会看到将它用作while循环的条件,while :实现了一个无限循环,代替了 5 | #更常见的while true。 6 | # : 结构也会被用在变量的条件设置中,例如:${var:=value} 如果没有 : ,shell 7 | #将试图把$var当作一条命令来处理。 8 | 9 | rm -f fred 10 | if [ -f fred ];then 11 | : 12 | else 13 | echo "file fred did not exist" 14 | fi 15 | 16 | exit 0 17 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/my_name.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #该实例演示了函数的参数是如何传递的,以及函数如何返回一个true或false值。 3 | #你使用一个参数来调用该脚本程序,该参数是你想要在问题中使用的名字。 4 | 5 | yes_or_no() { 6 | echo "Is your name $* ?" 7 | while true 8 | do 9 | echo -n "Enter yes or no: " 10 | read x 11 | case "$x" in 12 | y | yes ) return 0;; 13 | n | no ) return 1;; 14 | * ) echo "Answer yes or no" 15 | esac 16 | done 17 | } 18 | 19 | echo "Original parameters are $*" 20 | 21 | if yes_or_no "$1" 22 | then 23 | echo "Hi $1, nice name" 24 | else 25 | echo "Never mind" 26 | fi 27 | 28 | exit 0 29 | 30 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/qiuhe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # sumints - a program to sum a series of integers 3 | # 4 | if [ $# -eq 0 ] 5 | then 6 | echo "Usage: sumints integer list" 7 | exit 1 8 | fi 9 | 10 | sum=0 11 | until [ $# -eq 0 ] 12 | do 13 | sum=`expr $sum + $1` 14 | shift 15 | done 16 | echo $sum 17 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/qiuhe2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sum=0 3 | for INT in $* 4 | do 5 | sum=`expr $sum + $INT` 6 | done 7 | 8 | echo $sum 9 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/set.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #set命令的作用是为设置参数变量。许多命令的输出结果是以空格分隔的值, 3 | #如果需要使用输出结果中的某个域,这个命令就非常有用。 4 | 5 | echo "the date is $(date)" 6 | set $(date) 7 | echo The month is $2 8 | 9 | exit 0 10 | 11 | #这个程序把date命令的输出设置为参数列表,然后通过位置参数$2获得月份。 12 | 13 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/shift.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | #Filename: shift 4 | until [ $# -eq 0 ] 5 | do 6 | echo "Argument is $1 and `expr $# - 1` argument(s) remain" 7 | shift 8 | done 9 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/shift1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | while [ "$1" != "" ] 4 | do 5 | echo "$1" 6 | shift 7 | done 8 | 9 | exit 0 10 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/trap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #trap命令用于指定在接受到信号后将要采取的行动,trap命令的一种常见用途是在脚本 3 | #程序被中断时完成清理工作。 4 | #trap命令有两个参数,第一个参数是接受到指定信号时将要采取的行动,第二个参数是 5 | #要处理的信号名。 6 | #trap command signal 7 | 8 | trap 'rm -f /tmp/my_tmp_file_$$' INT 9 | echo "creating file /tmp/my_tmp_file_$$" 10 | date > /tmp/my_tmp_file_$$ 11 | 12 | echo "press interrupt (CTRL-C) to interrupt ...." 13 | while [ -f /tmp/my_tmp_file_$$ ] 14 | do 15 | echo File exists 16 | sleep 1 17 | done 18 | echo "The file no loger exists" 19 | 20 | trap INT 21 | echo "creating file /tmp/my_tmp_file_$$" 22 | date > /tmp/my_tmp_file_$$ 23 | 24 | echo "press interrupt (control-C) to interrupt ...." 25 | while [ -f /tmp/my_tmp_file_$$ ] 26 | do 27 | echo File exists 28 | sleep 1 29 | done 30 | 31 | echo we never get here 32 | exit 0 33 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/try_var.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | salutation="Hello" 3 | echo $salutation 4 | echo "The program $0 is now running" 5 | echo "The second parameter was $2" 6 | echo "The first parameter was $1" 7 | echo "The parameter list was $*" 8 | echo "The user's home directory is $HOME" 9 | 10 | echo "Please enter a new greeting" 11 | read salutation 12 | 13 | echo $salutation 14 | echo "The script is now complete" 15 | exit 0 16 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/unset.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #unset命令的作用是从环境中删除变量或函数。这个命令不能删除shell本身定义的 3 | #只读变量(如IFS)。 4 | 5 | foo="Hello World" 6 | echo $foo 7 | 8 | unset foo 9 | echo $foo 10 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/until.sh: -------------------------------------------------------------------------------- 1 | num=1 2 | until [ ! "$num" -le 10 ]; 3 | do 4 | echo "num is $num" 5 | num=$(($num+1)) 6 | done 7 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/until1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | int=1 3 | 4 | until [ $int -gt 5 ] 5 | do 6 | sq=`expr $int \* $int` 7 | echo $sq 8 | int=`expr $int + 1` 9 | done 10 | echo "completed" 11 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/untilwho.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #until是只有在条件为真时才执行循环 3 | #while是执行循环直到条件为真时退出 4 | 5 | #这是until例子,你设置一个警报,当某个特定的用户登录时,该警报就会启动,你 6 | #通过命令行将用户名传递给脚本程序。 7 | 8 | until who | grep "$1" > /dev/null 9 | do 10 | sleep 60 11 | done 12 | 13 | #now ring the bell and announce the expected user. 14 | 15 | echo -e '\a' 16 | echo "***** $1 has just logged in *****" 17 | 18 | exit 0 19 | 20 | #如果用户已经登录,那么循环就不需要执行。 21 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/while.sh: -------------------------------------------------------------------------------- 1 | num=1 2 | while [ "$num" -le 10 ]; 3 | do 4 | echo "num is $num" 5 | num=$(($num + 1)) 6 | done 7 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/while1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | #Filename:while1.sh 4 | int=1 5 | 6 | while [ $int -le 5 ] 7 | do 8 | sq=`expr $int \* $int` 9 | echo $sq 10 | int=`expr $int + 1` 11 | done 12 | echo "Job completed" 13 | 14 | -------------------------------------------------------------------------------- /0document/SHELL-BASE/whilepd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Enter password" 4 | read trythis 5 | 6 | while [ "$trythis" != "secret" ] 7 | do 8 | echo "Sorry, try again" 9 | read trythis 10 | done 11 | 12 | exit 0 13 | -------------------------------------------------------------------------------- /0document/SHELL打印颜色: -------------------------------------------------------------------------------- 1 | 例子:echo -e "\033[32mHello,world!\033[0m" 2 | 1.echo命令-e选项的作用是激活终端对反斜线转义符(\)的解释。 3 | 2.\033用于引导非常规字符序列,这里是引导设置输出属性。 4 | 3.[32m是将前景色设置为绿色,字母m表示设置的属性类别,数字 5 | **代表属性值。 6 | 4.\033[0m的作用是恢复属性为默认值,也就是说0m用于恢复默认值。 7 | ========================================================= 8 | \033[0m 关闭所用属性 9 | \033[1m 设置高亮度 10 | \033[4m 下划线 11 | \033[5m 闪烁 12 | \033[7m 反显 13 | \033[8m 消隐 14 | \033[30m 至 \033[37m 设置前景色 15 | \033[40m 至 \033[47m 设置背景色 16 | \033[nA 光标上移n行 17 | \033[nB 光标下移n行 18 | \033[nC 光标右移n行 19 | \033[nD 光标左移n行 20 | \033[y;xH 设置光标位置 21 | \033[2J 清屏 22 | \033[K 清除从光标到行尾的内容 23 | \033[s 保存光标位置 24 | \033[u 恢复光标位置 25 | \033[?25l 隐藏光标 26 | \033[?25h 显示光标 27 | \t 用作制表符 28 | \n 换行 29 | ======================================================== 30 | 数字代表的颜色如下: 31 | 字背景颜色范围:40-49 32 | 40:黑 33 | 41:深红 34 | 42:绿 35 | 43:黄色 36 | 44:蓝色 37 | 45:紫色 38 | 46:深绿 39 | 47:白色 40 | 字颜色范围:30-39 41 | 30:黑 42 | 31:红 43 | 32:绿 44 | 33:黄 45 | 34:蓝色 46 | 35:紫色 47 | 36:深绿 48 | 37:白色 49 | ======================================================= 50 | 同类多种设置项可以组合在一起,中间用分号(;)隔开。 51 | 例如:echo -e "\033[20;1H\033[1;4;32mHello,world\033[0m" 52 | ======================================================= 53 | ***python color*** 54 | print ("\033[1;31;40m") 55 | print ("*******************************") 56 | print ("*HOST:\t",a) 57 | print ("*TIME:\t",b) 58 | print ("*ARGS:\t",c) 59 | print ("*******************************") 60 | print ("\033[0m") 61 | ======================================================= 62 | -------------------------------------------------------------------------------- /0document/SHELL特殊变量: -------------------------------------------------------------------------------- 1 | ============================================================================= 2 | 变量名 含义 3 | ============================================================================= 4 | $0 shell或shell脚本的名字 5 | $* 以一对引号给出参数列表 6 | $@ 将各个参数分别加双引号返回 7 | $# 参数的个数 8 | $_ 代表上一个命令的最后一个参数 9 | $$ 代表所在命令的PID 10 | $! 代表最后执行的后台命令的PID 11 | $? 代表上一个命令执行后的退出状态(0成功 非0失败) 12 | ${var[@]} @代表变量var的所有参数 类似$@ 13 | ${#var[@]} 返回变量数组var所有参数的个数 类似于$# 14 | ============================================================================ 15 | 假设我们定义了一个变量为: 16 | file = /dir1/dir2/dir3/my.file.txt 17 | 用${}分别替换得到不同的值: 18 | 19 | ${file#*/} 删掉第一个/及其左边的字符串 dir1/dir2/dir3/my.file.txt 20 | ${file##*/} 删掉最后一个/及其左边的字符串 my.file.txt 21 | ${file#*.} 删掉第一个.及其左边的字符串 file.txt 22 | ${file##*.} 删掉最后一个.及其左边字符串 txt 23 | 24 | ${file%/*} 删掉最后一个/及其右边的字符串 /dir1/dir2/dir3 25 | ${file%%/*} 删掉第一个/及其右边的字符串 空置 26 | ${file%.*} 删掉最后一个.及其右边的字符串 /dir1/dir2/dir3/my.file 27 | ${file%%.*} 删掉第一个.及其右边的字符串 /dir1/dir2/dir3/my 28 | 29 | 记忆方法: 30 | #为删掉左边(键盘上#在$左边) 31 | %为删掉右边(键盘上%在$右边) 32 | 单一符号为最小匹配 两个符号为最大匹配 33 | 34 | 字符串提取 35 | ${file:0:5} 提取最左边的5个字节 /dir1 36 | ${file:5:5} 提取第5个字节右边的连续5个字节 /dir2 37 | 38 | 字符串替换 39 | ${file/dir/path} 将第一个dir替换为path /path1/dir2/dir3/my.file.txt 40 | ${file//dir/path} 将全部dir替换为path /path1/path2/path3/my.file.txt 41 | 42 | 变量的长度 43 | ${#file} 44 | 45 | 数组预算 46 | A=(a b c def) 47 | ${A[@]} 可得全部数组 a b c def 48 | ${A[*]} 可得全部数组 a b c def 49 | ${A[0]} 可得第一个组数 a 50 | ${A[1]} 可得第二个组数 b 51 | ${#A[@]} 可得到数值4 4 52 | ${#A[*]} 可得到数值4 4 53 | ${#A[0]} 可得到第一个组数a的长度 1 54 | ${#A[3]} 可得到第四个组数def的长度 3 55 | ============================================================================= 56 | -------------------------------------------------------------------------------- /0document/SHELL特殊用法: -------------------------------------------------------------------------------- 1 | ============================================================ 2 | 1.函数中输出函数名:$FUNCNAME 3 | function log() { 4 | echo ${FUNCNAME[@]} 5 | } 6 | function action() { 7 | log 8 | } 9 | action 10 | 此变量是一个数组,返回的是函数名称,如嵌套调用函数,会按调用 11 | 顺序排列所有函数的数组。 12 | 输出内容:log action 13 | 用途:日志函数或者函数名传递等。 14 | 如果只想获得当前函数的名称,直接输出:echo $FUNCNAME 15 | ============================================================ 16 | 2.循环中的跳转:continue [n] 17 | function son() { 18 | for z in 1 2 3; do 19 | if true; then 20 | echo $x,$y,$z 21 | continue 3 22 | fi 23 | done 24 | } 25 | function father() { 26 | for x in 1 2 3; do 27 | for y in 1 2 3; do 28 | son 29 | done 30 | done 31 | } 32 | father 33 | 声明:continue可用于子函数,跳转到父函数中的指定层次循环中。 34 | n值从1开始(不写默认为1,数字越大则层数越高,超过总循环层数 35 | 时值为最大层数); 36 | 以上代码中只有最上层x会正常循环完,其余子层都在首轮跳出,此 37 | 时n的最大值为3; 38 | 若在son后加一个&使其在后台运行,此时continue能控制y,z两层, 39 | 但不能跳转到x,即n的最大值为2. 40 | ============================================================ 41 | 3.uniq注意事项 42 | 该命令uniq只会比较相邻的行而不会跨向比较,除非必要,否则最好 43 | 先进行排序:sort -u 44 | ============================================================ 45 | 4.变量简介引用 46 | a=1 47 | b=a 48 | echo ${!b} //输出1 49 | eval echo \$$b //输出1 50 | ============================================================ 51 | 5.sed模式空间 52 | printf 'aaa\naaa' | sed 's/a/A/' 53 | printf 'aaa\naaa' | sed 's/a/A/g' 54 | printf 'aaa\naaa' | sed ':a;N;$!ba;s/a/A/' 55 | printf 'aaa\naaa' | sed ':a;N;$!ba;s/a/A/g' 56 | 第一个会替换每一行的第一个小写a,第二与第四个则会替换所有小 57 | 写a,第三个只会替换第一行的第一个小写a。 58 | 如果原始数据只有一行,那么最后两种写法均不会生效,因此,只是 59 | 替换第一行的第一个字符的写法为最好为: 60 | printf 'aaa\naaa\n' | sed '1s/a/A/' 61 | 其中有 :a N $!ba 这三个字段是为了构建一个循环将整个文件逐行 62 | 添加至pattern space(匹配空间),用Next命令将一个新的输入行追 63 | 加至pattern space的当前行,最后一行不跳转至pattern space中, 64 | 其他行都跳转至匹配空间。 65 | a append N next b break q quit $ 变量环境 ! 非 c 替换 66 | shell awk sed这三者均是逐行执行的 67 | ============================================================ 68 | -------------------------------------------------------------------------------- /0document/diff-patch: -------------------------------------------------------------------------------- 1 | =========================================================== 2 | diff命令可以接目录和文件,并且文件只有是文本文件时才有效。 3 | diff命令用于比较两个文件的差异,它可以被制作成补丁文件,使 4 | patch命令对相应的文件打补丁。 5 | diff命令接收两个目录作为参数时,会比较两个目录下名字相同的 6 | 文本文件,并列出不同的二进制文件,公共子目录和只在一个目录 7 | 中出现的文件。 8 | =========================================================== 9 | *diff/patch用集合来说,diff是对两个集合求差,patch是求和。 10 | **diff a b > c 生成a和b的diff文件c 11 | **patch a c 给a打上diff文件c得到b 12 | **patch -R b c b还原为a 13 | =========================================================== 14 | *diff/patch命令用来给linux的kernel打补丁。 15 | *生成补丁* 16 | **diff -uNr linux-2.6.xxx linux-2.6.xxx.1 > diff.patch 17 | **选项-u 统一的格式 -N 对已创建文件不做变更 -r 递归目录 18 | *升级内核* 19 | **cp diff.patch linux-2.6.xxx/ 20 | **cd linux-2.6.xxx 21 | **patch -p1 < diff.patch 22 | **-p0 使用完整路径名 -p1 除去前导斜杠 23 | **-p4 除去前导斜杠和前三个目录 24 | ========================================================== 25 | **xz -dv linux-4.0.tar.xz | tar xvf - 26 | **最后的横杠表示使用标准输入输出 27 | **xz -dv ../patch-4.x.xz | patch -p1 28 | ========================================================== 29 | *解压缩linux内核kernel* 30 | **压缩内核** 31 | **tar cvf linux-4.0 32 | **xz -zv linux-4.0.tar 33 | **解压内核** 34 | **xz -dv linux-4.0.tar.xz 35 | **tar xvf linux-4.0.tar 36 | ========================================================= 37 | -------------------------------------------------------------------------------- /0document/sublime快捷键: -------------------------------------------------------------------------------- 1 | ================================================================ 2 | ctrl+m 跳转到对应的括号 ctrl+shitf+m 扩展选择(括号内) 3 | ctrl+f 查找 4 | ctrl+h 查找替换 5 | ctrl+r 前往代码的方法或类 6 | ctrl+p 搜索项目中的文件 7 | ctrl+g 跳转到第几行 8 | ctrl+e 形成HTML中的标签(可以自定义) 9 | ctrl+l 选择行,重复可依次增加选择下一行 10 | ****************ctrl+shift+l 选择多行编辑 11 | ctrl+d 选择单词,重复可依次选择下一个相同的单词并编辑 12 | ctrl+i 展示面板 13 | ctrl+q 记录和停止宏(ctrl+shitf+q:播放) 14 | ctrl+b build 15 | ctrl+t 颠倒transpose 16 | ctrl++ 增大字体 17 | ctrl+- 减小字体 18 | ctrl+/ 当前行注释状态切换(ctrl+shift+/当前位置注释切换) 19 | ctrl+` python接口 20 | ctrl+; 展示文档中的关键内容 跳转该关键字 并显示所有同项 21 | ctrl+[ 缩进 22 | ctrl+] 不缩进 23 | ctrl+a 全选 24 | ctrl+c 复制 25 | ctrl+v 粘贴 26 | ctrl+x 剪切 27 | ctrl+n 新建文件 28 | ctrl+s 保存 ctrl+shitf+s 另存为 29 | ctrl+w 关闭 30 | ctrl+z 撤销 31 | ctrl+y 重复或重做 32 | ctrl+left 按\w规则跳跃 alt+left 单词 shitf+left 移动并选择 33 | ctrl+right 按\w规则跳跃 alt+right 单词 shitf+right 移动并选择 34 | ctrl+up 滚动行 35 | ctrl+down 滚动行 36 | ctrl+tab 打开文档之间切换 37 | ctrl+f2 标签状态切换 f2 下一个标签 shift+f2 上一个标签 38 | ****************ctrl+shitf+f2 清除所有标签 alt+f2 选中所有标签 39 | ctrl+f3 下一个匹配项 f3 下一个匹配项 shitf+f3 上一个匹配项 40 | ctrl+f4 关闭文件 41 | ctrl+f9 行排序 f9 行排序 42 | ================================================================== 43 | ctrl+k,ctrl+d 所选单词相同项的下一个 44 | ctrl+k,ctrl+u 大写 45 | ctrl+k,ctrl+l 小写 46 | ctrl+k,ctrl+b 切换侧边栏显示状态 47 | ctrl+k,ctrl+c 在中央显示 48 | ctrl+k,ctrl+0 不折叠代码 49 | ctrl+k,ctrl+1 按层级折叠代码(1-9) 50 | ================================================================== 51 | alt+shift+w 插入

段落标签 52 | alt+1 选择打开的文件,数字代表文件(1-9) 53 | ctrl+tab 此快捷键和alt+1类似 54 | ctrl+shift+l 选择多行编辑 55 | ctrl+shift+/ 当前位置插入注释,块注释 56 | ctrl+shift+d 复制当前行并粘贴追加到下一行 57 | ================================================================== 58 | alt+shift+1 分屏只显示一屏 59 | alt+shift+2 分屏列方向显示两屏 60 | alt+shift+3 分屏列方向显示三屏 61 | alt+shift+4 分屏列方向显示四屏 62 | alt+shift+5 分屏田字四屏 63 | alt+shift+8 分屏行方向显示两屏 64 | alt+shift+9 分屏行方向显示三屏 65 | ================================================================= 66 | -------------------------------------------------------------------------------- /1Go语言/Unicode.go: -------------------------------------------------------------------------------- 1 | //unicode字符的定义和使用 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var ch1 rune 10 | ch1 = '中' 11 | ch2 := 22269 12 | fmt.Println(ch1) //unicode字符直接输出为整数形式 13 | fmt.Println(string(ch1)+string(ch2)) //要以Unicode字符输出需先转换 14 | } -------------------------------------------------------------------------------- /1Go语言/bitcomputing.go: -------------------------------------------------------------------------------- 1 | //位运算 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var a,b int=6,11 10 | fmt.Println(^a) //取反运算 11 | fmt.Println(a&b) //按位与 12 | fmt.Println(a|b) //按位或 13 | fmt.Println(a&^b) //标志位清除 14 | fmt.Println(a<<2) //左移2位 15 | fmt.Println(b>>2) //右移2位 16 | } -------------------------------------------------------------------------------- /1Go语言/bool.go: -------------------------------------------------------------------------------- 1 | // bool型变量的定义与使用 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | var b1, b2 bool 10 | b1 = true 11 | b2 = false 12 | fmt.Println(b1) 13 | fmt.Println(b2) 14 | } 15 | -------------------------------------------------------------------------------- /1Go语言/byte.go: -------------------------------------------------------------------------------- 1 | //字节型数据的定义和使用 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var ch1,ch2 byte 10 | ch1=65 11 | ch2='A' 12 | fmt.Println(string(ch1)) //要以字符型输出需先转换 13 | fmt.Println(ch2) //字节型数据直接输出为整数形式 14 | } -------------------------------------------------------------------------------- /1Go语言/complex.go: -------------------------------------------------------------------------------- 1 | //复数的定义和使用 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var cp1,cp2 complex64 10 | cp1=1.2+3.4i 11 | cp2=cp1 12 | cp3:=complex(1.2,3.4) 13 | fmt.Println(cp1) 14 | fmt.Println(cp2) 15 | fmt.Println(cp3) 16 | } -------------------------------------------------------------------------------- /1Go语言/complex2.go: -------------------------------------------------------------------------------- 1 | //获取复数的实部和虚部 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var cp1 complex64 10 | cp1=1.2+3.4i 11 | fmt.Println("real:",real(cp1)) 12 | fmt.Println("real:",real(cp1)) 13 | } -------------------------------------------------------------------------------- /1Go语言/const.go: -------------------------------------------------------------------------------- 1 | //常量 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | const( 9 | a=100 10 | b=3.14 11 | c=false 12 | ) 13 | 14 | func main(){ 15 | fmt.Println(a) 16 | fmt.Println(b) 17 | fmt.Println(c) 18 | } -------------------------------------------------------------------------------- /1Go语言/const2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import( 4 | "fmt" 5 | ) 6 | 7 | const i=1 8 | 9 | const( 10 | a=i 11 | b=i+1 12 | c=i+2 13 | ) 14 | 15 | func main(){ 16 | fmt.Println(a) 17 | fmt.Println(b) 18 | fmt.Println(c) 19 | } -------------------------------------------------------------------------------- /1Go语言/const3.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import( 4 | "fmt" 5 | ) 6 | 7 | const ( 8 | a=100 9 | b 10 | c 11 | ) 12 | 13 | func main(){ 14 | fmt.Println(a) 15 | fmt.Println(b) 16 | fmt.Println(c) 17 | } -------------------------------------------------------------------------------- /1Go语言/const4.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import( 4 | "fmt" 5 | ) 6 | 7 | const( 8 | a,b=1,true 9 | c,d 10 | ) 11 | 12 | func main(){ 13 | fmt.Println(a) 14 | fmt.Println(b) 15 | fmt.Println(c) 16 | fmt.Println(d) 17 | } -------------------------------------------------------------------------------- /1Go语言/const5.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import( 4 | "fmt" 5 | ) 6 | 7 | const( 8 | a=1.2+3.4i 9 | b=real(a) 10 | c=imag(a) 11 | ) 12 | 13 | func main(){ 14 | fmt.Println(a) 15 | fmt.Println(b) 16 | fmt.Println(c) 17 | } -------------------------------------------------------------------------------- /1Go语言/eq.go: -------------------------------------------------------------------------------- 1 | //赋值运算 2 | package main 3 | 4 | import( 5 | "fmt" 6 | "math" 7 | ) 8 | 9 | func main(){ 10 | var a,b int 11 | var str string = "hello world!" 12 | var pi float64 13 | a=100 14 | b=len(str) 15 | pi=math.Pi 16 | fmt.Println(a) 17 | fmt.Println(b) 18 | fmt.Println(str) 19 | fmt.Println(pi) 20 | } -------------------------------------------------------------------------------- /1Go语言/eq1.go: -------------------------------------------------------------------------------- 1 | //算数运算 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var a,b int=7,163 10 | var c,d float32=2.5,6.3 11 | var ch1,ch2 rune='中','国' 12 | fmt.Println(string(ch1)+string(ch2)) 13 | fmt.Println(d-c) 14 | fmt.Println(c*d) 15 | fmt.Println(b/a) 16 | fmt.Println(b%a) 17 | } -------------------------------------------------------------------------------- /1Go语言/float.go: -------------------------------------------------------------------------------- 1 | //浮点型数据的舍入误差 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var f1,f2 float32 10 | f1=12356.789e5 11 | f2=f1+20 12 | fmt.Println(f2) 13 | } -------------------------------------------------------------------------------- /1Go语言/globalvar.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import( 4 | "fmt" 5 | ) 6 | /************************************ 7 | var i int 8 | func main(){ 9 | i=100 10 | fmt.Println(i) 11 | } 12 | ************************************/ 13 | 14 | /*********************************** 15 | var( 16 | a,b,c int 17 | ) 18 | func main(){ 19 | a,b,c=100,200,300 20 | fmt.Println(a) 21 | fmt.Println(b) 22 | fmt.Println(c) 23 | } 24 | ************************************/ 25 | 26 | func main(){ 27 | var a,b,c,d int 28 | a,_,c,d=1,2,3,4 29 | fmt.Println(a) 30 | fmt.Println(b) 31 | fmt.Println(c) 32 | fmt.Println(d) 33 | } -------------------------------------------------------------------------------- /1Go语言/int.go: -------------------------------------------------------------------------------- 1 | //int整形变量的定义与使用 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var sum int 10 | var a int = 100 11 | b:=28 12 | sum=a+b 13 | fmt.Println(sum) 14 | } -------------------------------------------------------------------------------- /1Go语言/int2.go: -------------------------------------------------------------------------------- 1 | //整形数据的溢出 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var a int8=127 10 | fmt.Println(a,a+1) 11 | } -------------------------------------------------------------------------------- /1Go语言/iota.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import( 4 | "fmt" 5 | ) 6 | /******************************************** 7 | const( 8 | sunday =iota//0 9 | monday =iota//1 10 | tuesday =iota//2 11 | wednesday =iota//3 12 | thursday =iota//4 13 | friday =iota//5 14 | saturday =iota//6 15 | ) 16 | Go语言的常量和枚举之间的转换时非常灵活的,它在常量组中使用计数器iota, 17 | iota从0开始,常量组中每定义一个常量iota自动递增1。 18 | const( 19 | sunday =iota//0 20 | monday //1 21 | tuesday //2 22 | wednesday //3 23 | thursday //4 24 | friday //5 25 | saturday //6 26 | ) 27 | **********************************************/ 28 | 29 | /*********************************************** 30 | 常量组中每定义一个常量,iota就会自动递增1,而每遇到一个 31 | const关键字,iota就会重置为0。 32 | **********************************************/ 33 | const( 34 | a='A' 35 | b 36 | c=iota 37 | d 38 | ) 39 | const( 40 | e='E' 41 | f=iota 42 | ) 43 | 44 | func main(){ 45 | fmt.Print(a) 46 | fmt.Println(b) 47 | fmt.Println(c) 48 | fmt.Println(d) 49 | fmt.Println(e) 50 | fmt.Println(f) 51 | } -------------------------------------------------------------------------------- /1Go语言/localvar.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import( 4 | "fmt" 5 | ) 6 | 7 | func main(){ 8 | var a int=100 9 | fmt.Println(a) 10 | f() 11 | } 12 | func f(){ 13 | var a float32=3.14 14 | fmt.Println(a) 15 | } -------------------------------------------------------------------------------- /1Go语言/logic.go: -------------------------------------------------------------------------------- 1 | //逻辑运算 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var a,b bool=true,false 10 | fmt.Println(!a) //逻辑非 11 | fmt.Println(a&&b) //逻辑与 12 | fmt.Println(a||b) //逻辑或 13 | } -------------------------------------------------------------------------------- /1Go语言/math.go: -------------------------------------------------------------------------------- 1 | //使用math包查看整形数据的最大值,最小值 2 | package main 3 | 4 | import( 5 | "fmt" 6 | "math" 7 | ) 8 | 9 | func main(){ 10 | fmt.Printf("Min(int8)=%v,Max(int8)=%v\n",math.MinInt8,math.MaxInt8) 11 | fmt.Printf("Min(int16)=%v,Max(int16)=%v\n",math.MinInt16,math.MaxInt16) 12 | fmt.Printf("Min(int32)=%v,Max(int32)=%v\n",math.MinInt32,math.MaxInt32) 13 | } -------------------------------------------------------------------------------- /1Go语言/pointer.go: -------------------------------------------------------------------------------- 1 | //指针变量的定义和引用 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var i int 10 | var i_pointer* int 11 | i=100 12 | i_pointer=&i //将i的内存地址存放到指针变量i_pointer中 13 | fmt.Println(*i_pointer) 14 | } -------------------------------------------------------------------------------- /1Go语言/relationship.go: -------------------------------------------------------------------------------- 1 | //关系运算 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var a,b int=5,10 10 | var ch1,ch2 byte = 'a','b' 11 | fmt.Println(a>b) 12 | fmt.Println(b>=8) 13 | fmt.Println(ch1=90)&&(grade<=100): 14 | //成绩在90-100区间等级为A 15 | fmt.Println("A") 16 | case(grade>=80)&&(grade<90): 17 | //成绩在80-89区间等级为B 18 | fmt.Println("B") 19 | case(grade>=70)&&(grade<80): 20 | //成绩在70-79区间等级为C 21 | fmt.Println("C") 22 | default: 23 | //成绩在70以下等级为D 24 | fmt.Println("D") 25 | } 26 | } -------------------------------------------------------------------------------- /3Go选择结构程序/11.go: -------------------------------------------------------------------------------- 1 | //求解一元二次方程 2 | package main 3 | 4 | import( 5 | "fmt" 6 | "math" 7 | ) 8 | 9 | func main(){ 10 | //设x1,x2为两个实数根,disc为判别式 11 | var a,b,c,disc,x1,x2,p,q float64 12 | //设cpx1,cpx2为两个共轭复根 13 | var cpx1,cpx2 complex128 14 | fmt.Println("请输入一元二次方程三个系数:") 15 | fmt.Scanf("%f,%f,%f",&a,&b,&c) 16 | if a==0 { 17 | fmt.Println("系数a为0不是一元二次方程!") 18 | }else{ 19 | disc=b*b-4*a*c 20 | p=-b/(2*a) 21 | q=math.Sqrt(disc)/(2*a) 22 | if disc==0 { 23 | x1=p 24 | x2=p 25 | fmt.Printf("判别式等于0有两个相等的实根:x1=x2=%8.2f\n",p) 26 | }else if disc > 0 { 27 | x1=p+q 28 | x2=p-q 29 | fmt.Printf("判别式大于0有两个不相等的实根:x1=%8.2f x2=%8.2f\n",x1,x2) 30 | }else if disc < 0 { 31 | q=math.Sqrt(math.Abs(disc))/(2*a) 32 | cpx1=complex(p,q) 33 | cpx2=complex(p,-q) 34 | fmt.Printf("判别式小于0有两个共轭的复根:cpx1=%8.2f cpx2=%8.2f\n",cpx1,cpx2) 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /3Go选择结构程序/12.go: -------------------------------------------------------------------------------- 1 | //打印中日期和星期信息 2 | package main 3 | 4 | import( 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | func main(){ 10 | //获取时间戳 11 | t:=time.Now() 12 | //按年月日格式输出日期信息 13 | fmt.Print(t.Format("2006年01月02日")) 14 | switch t.Weekday().String(){ 15 | case "Sunday": 16 | fmt.Printf("星期天") 17 | case "Monday": 18 | fmt.Printf("星期一") 19 | case "Tuesday": 20 | fmt.Printf("星期二") 21 | case "Wednesday": 22 | fmt.Printf("星期三") 23 | case "Thursday": 24 | fmt.Printf("星期四") 25 | case "Friday": 26 | fmt.Printf("星期五") 27 | case "Saturday": 28 | fmt.Printf("星期六") 29 | } 30 | } -------------------------------------------------------------------------------- /3Go选择结构程序/2.go: -------------------------------------------------------------------------------- 1 | //if语句的使用,关系表达式或逻辑表达式的值作为判断条件 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var a,b int 10 | //通过scanln()函数,从键盘输入a,b的值 11 | fmt.Scanln(&a,&b) 12 | //关系表达式的值作为判断条件 13 | if a>b { 14 | fmt.Println("a>b") 15 | } 16 | //逻辑表达式的值作为判断条件 17 | if(a!=0)&&(a>0){ 18 | fmt.Println("a is positive number") 19 | } 20 | if(a!=0)&&(a<0){ 21 | fmt.Println("a is negative number") 22 | } 23 | //if语句外的后续语句 24 | fmt.Println("OVER") 25 | } -------------------------------------------------------------------------------- /3Go选择结构程序/3.go: -------------------------------------------------------------------------------- 1 | //使用if else语句找出最大数 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var a,b int 10 | //通过scanln()函数,从键盘吧输入a,b的值 11 | fmt.Scanln(&a,&b) 12 | if a>b { 13 | //条件为TRUE执行这里 14 | fmt.Printf("MAX=%d\n",a) 15 | }else{ 16 | //条件为false执行这里 17 | fmt.Printf("MAX=%d\n",b) 18 | } 19 | } -------------------------------------------------------------------------------- /3Go选择结构程序/4.go: -------------------------------------------------------------------------------- 1 | //使用多条件判断打印成绩等级 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var grade int 10 | //通过scanln()函数,从键盘输入成绩grade 11 | fmt.Scanln(&grade) 12 | if (grade>=90)&&(grade<=100){ 13 | //成绩在90-100区间等级为A 14 | fmt.Println("A") 15 | }else if(grade>=80)&&(grade<90){ 16 | //成绩在80-90区间等级为B 17 | fmt.Println("B") 18 | }else if(grade>=70)&&(grade<80){ 19 | //成绩在70-79区间等级为C 20 | fmt.Println("C") 21 | }else{ 22 | //成绩在70以下等级为D 23 | fmt.Println("D") 24 | } 25 | } -------------------------------------------------------------------------------- /3Go选择结构程序/5.go: -------------------------------------------------------------------------------- 1 | //使用if嵌套语句判断闰年 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var year int 10 | //通过scanln()函数,从键盘输入year的值 11 | fmt.Scanln(&year) 12 | if year%4==0 { 13 | if year%100==0{ 14 | if year%400==0{ 15 | //能被4整除,且能被100整除,且能被400整除是闰年 16 | fmt.Printf("%d is leap year.\n",year) 17 | }else{ 18 | //能被4整除,且能被100整除,但不能被400整除不是闰年 19 | fmt.Printf("%d is not leap year.\n",year) 20 | } 21 | }else { 22 | //能被4整除,且不能够被100整除是闰年 23 | fmt.Printf("%d is leap year.\n",year) 24 | } 25 | }else{ 26 | //不能被4整除不是闰年 27 | fmt.Printf("%d is not leap year.\n",year) 28 | } 29 | } -------------------------------------------------------------------------------- /3Go选择结构程序/6.go: -------------------------------------------------------------------------------- 1 | //if语句初始化条件表达式 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | a:=10 10 | if a:=1;a>0{ 11 | //打印if语句块中条件变量a的值 12 | fmt.Println(a) 13 | } 14 | //打印if语句块外变量a的值 15 | fmt.Println(a) 16 | } -------------------------------------------------------------------------------- /3Go选择结构程序/7.go: -------------------------------------------------------------------------------- 1 | //switch语句实现简单计算器 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | //操作数a,b 10 | var a,b int 11 | //算术运算符+-*/ 12 | var op byte 13 | //通过scanf()函数,格式化从键盘输入操作数和云算数 14 | fmt.Scanf("%d %c %d",&a,&op,&b) 15 | switch op { 16 | case '+': 17 | fmt.Println(a+b) //加法 18 | case '-': 19 | fmt.Println(a-b) //减法 20 | case '*': 21 | fmt.Println(a*b) //乘法 22 | default: 23 | fmt.Println(a/b) //除法 24 | } 25 | } -------------------------------------------------------------------------------- /3Go选择结构程序/8.go: -------------------------------------------------------------------------------- 1 | //多选项case语句 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | //搜索字符串变量 10 | var searchstr string 11 | //通过scanf()函数,格式化从键盘输入操作数和云算数 12 | fmt.Scanf("%s",&searchstr) 13 | switch searchstr{ 14 | case "c","C": 15 | //搜索字符串是c或C都执行下面语句 16 | fmt.Println("C programing language") 17 | case "go","golang": 18 | //搜索字符串是go或golang都执行下面语句 19 | fmt.Println("Go programing language") 20 | case "java": 21 | //搜索字符串是Java执行下面语句 22 | fmt.Println("Java programing language") 23 | default: 24 | //没有搜索到 25 | fmt.Println("Not find the result!") 26 | } 27 | } -------------------------------------------------------------------------------- /3Go选择结构程序/9.go: -------------------------------------------------------------------------------- 1 | //fallthrough语句的使用 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var i int 10 | //通过scanf()函数,格式化从键盘输入变量i的值 11 | fmt.Scanf("%d",&i) 12 | switch i { 13 | case 0: 14 | fmt.Println("0") 15 | case 1: 16 | fmt.Println("1") 17 | case 2: 18 | fmt.Println("2") 19 | fallthrough //继续执行下一分支 20 | case 3: 21 | fmt.Println("3") 22 | default: 23 | fmt.Println("4") 24 | } 25 | } -------------------------------------------------------------------------------- /4Go循环结构程序/1.go: -------------------------------------------------------------------------------- 1 | //使用基本循环控制结构统计单词中的某个字符数 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var words string 10 | var ch byte 11 | var ln,count int 12 | //从键盘格式化输入单词 13 | fmt.Scanf("%s",&words) 14 | fmt.Println("\n") 15 | //输入要统计的字符 16 | fmt.Scanf("%c",&ch) 17 | //计算单词的字节长度 18 | ln=len(words) 19 | /******************************************** 20 | 算法:从单词的第一个字符开始扫描,找到符合条件的字符, 21 | 计数器加1 22 | ********************************************/ 23 | for i:=0; i GOAL { 37 | fmt.Printf("数字%d有点大,请再试一试...\n",data) 38 | count++ 39 | str="" 40 | goto LABEL1 41 | }else if data < GOAL { 42 | fmt.Printf("数字%d有点小,请在试一试...\n",data) 43 | count++ 44 | str="" 45 | goto LABEL1 46 | }else { 47 | fmt.Printf("恭喜你,猜中了!") 48 | break 49 | } 50 | } 51 | fmt.Printf("你一共猜了%d次才猜对了。",count) 52 | } -------------------------------------------------------------------------------- /4Go循环结构程序/12.go: -------------------------------------------------------------------------------- 1 | //统计字符串中的字符,数字个数 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | //str用于存储输入字符串 10 | var str string 11 | //下列变量分别用于英文字符,数字,其他字符个数统计 12 | var charCount,numCount,otherCount int 13 | fmt.Println("请输入字符串...") 14 | fmt.Scanf("%s",&str) 15 | for _,v:=range str { 16 | if v>=48 && v<=57 { 17 | numCount++ 18 | }else if (v>=65&&v<=90)||(v>=97&&v<=122) { 19 | charCount++ 20 | }else{ 21 | otherCount++ 22 | } 23 | } 24 | fmt.Printf("共有%d个数字\n",numCount) 25 | fmt.Printf("%d个英文字母\n",charCount) 26 | fmt.Printf("%d个其他字符\n",otherCount) 27 | } -------------------------------------------------------------------------------- /4Go循环结构程序/2.go: -------------------------------------------------------------------------------- 1 | //按照S型排座位 2 | package main 3 | 4 | import( 5 | "fmt" 6 | "strconv" 7 | ) 8 | 9 | func main(){ 10 | //定义并初始化座位为10行5列 11 | var row,col int = 10,5 12 | //定义座位号打印字符串 13 | var seatNo string 14 | for k:=0;k=k*col;i,j=i+1,j-1 { 16 | if k%2==0 { 17 | seatNo+=" "+strconv.Itoa(i) 18 | }else{ 19 | seatNo+=" "+strconv.Itoa(j) 20 | } 21 | } 22 | fmt.Printf("%s\n",seatNo) 23 | seatNo="" 24 | } 25 | } -------------------------------------------------------------------------------- /4Go循环结构程序/3.go: -------------------------------------------------------------------------------- 1 | //使用条件循环控制结构近似求π 2 | package main 3 | 4 | import( 5 | "fmt" 6 | "math" 7 | ) 8 | 9 | func main(){ 10 | var s int=1 11 | var n,t,pi float64=1.0,1.0,0 12 | for math.Abs(t)>1e-6 { 13 | pi=pi+t 14 | n=n+2 15 | s=-s 16 | t=float64(s)/n 17 | } 18 | pi=pi*4 19 | fmt.Printf("pi=%10.6f\n",pi) 20 | } -------------------------------------------------------------------------------- /4Go循环结构程序/4.go: -------------------------------------------------------------------------------- 1 | //简单键盘文本输入程序 2 | package main 3 | 4 | import( 5 | "fmt" 6 | "bufio" 7 | "os" 8 | ) 9 | 10 | func main(){ 11 | var c byte //存放每个按键ASCII码 12 | var str string //存放输入字符串流 13 | //初始化标准输入设备 14 | r:=bufio.NewReader(os.Stdin) 15 | //初始化标准输出设备 16 | w:=bufio.NewWriter(os.Stdout) 17 | for i:=0; ;i++{ 18 | c,_=r.ReadByte() 19 | if c==10 { 20 | break //如果是回车停止接受退出循环 21 | }else{ 22 | //将接受到的字符写入标准输出设备 23 | w.WriteByte(c) 24 | w.Flush() 25 | //生成字符串 26 | str+=string(c) 27 | } 28 | } 29 | fmt.Printf("\n") 30 | fmt.Println(str) 31 | } -------------------------------------------------------------------------------- /4Go循环结构程序/5.go: -------------------------------------------------------------------------------- 1 | //使用循环嵌套打印九九乘法表 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var row,col int 10 | for row=1;row<9;row++{ 11 | for col=1;col<=row;col++{ 12 | fmt.Printf("%d*%d=%d ",row,col,row*col) 13 | } 14 | fmt.Printf("\n") 15 | } 16 | } -------------------------------------------------------------------------------- /4Go循环结构程序/6.go: -------------------------------------------------------------------------------- 1 | //判断素数 2 | package main 3 | 4 | import( 5 | "fmt" 6 | "math" 7 | ) 8 | 9 | func main(){ 10 | var num,i,k int 11 | //从键盘格式化输入要判断的数num 12 | fmt.Scanf("%d",&num) 13 | //对num开方并取整求k 14 | k=int(math.Sqrt(float64(num))) 15 | for i=2;i<=k;i++ { 16 | if num%i==0{ 17 | break //num能被2-k中的一个数整除,跳出循环 18 | } 19 | } 20 | if i>k { 21 | fmt.Printf("The number %d is a prime number.\n",num) 22 | }else{ 23 | fmt.Printf("The number %d is not a prime number.\n",num) 24 | } 25 | } -------------------------------------------------------------------------------- /4Go循环结构程序/7.go: -------------------------------------------------------------------------------- 1 | //continue语句的使用 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var n int 10 | for n=10;n<30;n++{ 11 | if n%3!=0{ 12 | continue //不能被3整除,终止本次循环,返回条件测试 13 | } 14 | fmt.Printf("%d",n) 15 | fmt.Printf("\n") 16 | } 17 | } -------------------------------------------------------------------------------- /4Go循环结构程序/8.go: -------------------------------------------------------------------------------- 1 | //goto语句实现直到型循环计算1-100的累加和 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var i,sum = 1,0 10 | HERE: 11 | sum=sum+i 12 | i++ 13 | if i<=100 { 14 | goto HERE 15 | } 16 | fmt.Println(sum) 17 | } 18 | /************************************************** 19 | 和break,continue语句不同,goto语句天生就要和标签(label) 20 | 配合起来使用。goto语句可以调整程序执行的位置,它可以让程序 21 | 无条件跳转到一个标签(label)之处继续执行。 22 | LABEL: 23 | : 24 | : 25 | break LABEL 26 | *************** 27 | LABEL: 28 | : 29 | : 30 | continue LABEL 31 | *************** 32 | LABEL: 33 | : 34 | : 35 | goto LABEL 36 | *************** 37 | 总结:break,continue,goto语句都可以和标签配合使用, 38 | 但作用有所区别。通常情况下,如果不使用标签break,continue 39 | 语句只能跳出本层循环。配合标签使用以后,break,continue 40 | 语句就可以跳出多重循环了,这时就不必使用goto语句了。 41 | ***************************************************/ -------------------------------------------------------------------------------- /4Go循环结构程序/9.go: -------------------------------------------------------------------------------- 1 | //for range语句对数据对象进行遍历 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var str string="Golang" 10 | //设k为健,v为值 11 | for k,v:=range str { 12 | fmt.Printf("s[%d]=%c\n",k,v) 13 | } 14 | } 15 | /********************************************** 16 | range可以看作是一个迭代器,当它被调用时,它会从所遍历 17 | 的数组返回一个键值对(key-value pair)。基于不同的数据 18 | 对象,range返回不同的键值对。当对数组或切片进行遍历时 19 | range返回数组下标最为键(key),数组下标所对应的元素 20 | 作为值(value)。for range语句还可以对字典(map), 21 | 通道(channel)进行迭代操作。有时可能只需要range返回 22 | 的键值中的一个,这时只需要使用占位符"_"即可。 23 | ********************************************* 24 | for _,v:=range str { 25 | 26 | } 27 | ********************************************* 28 | for k,_:=range str { 29 | 30 | } 31 | ********************************************* 32 | for k:=range str { 33 | 34 | } 35 | 此种也可以直接将”值“丢掉。这是因为k本身就在第一位, 36 | 会首先获取数据。 37 | ********************************************/ -------------------------------------------------------------------------------- /5数组切片和字典/1.go: -------------------------------------------------------------------------------- 1 | //数组的定义 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var i int 10 | var arr1 [5] int 11 | for i=0; i<=4;i++ { 12 | arr1[i]=i+1 13 | } 14 | fmt.Println(arr1) 15 | } -------------------------------------------------------------------------------- /5数组切片和字典/10.go: -------------------------------------------------------------------------------- 1 | //切片的复制 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var slice1=[]int{1,2,3,4,5,6,7,8,9,10} 10 | var slice2=make([]int,3,5) 11 | var n int 12 | //只能复制三个元素 13 | n=copy(slice2,slice1) 14 | fmt.Println(n,slice2,len(slice2),cap(slice2)) 15 | //sllice3和slice1指向同一底层数组 16 | slice3:=slice1[3:6] 17 | fmt.Println(slice1,slice3) 18 | //复制后元素重叠 19 | n=copy(slice3,slice1[1:5]) 20 | fmt.Println(n,slice1,slice3) 21 | } 22 | /*********************************************** 23 | 由于1和3指向同一个底层数组,所以复制后元素重叠。3刚创建时, 24 | 他引用的是底层数组的【4,5,6】复制后1将【2,3,4】三个元素 25 | 复制给3,所以最后3的元素【2,3,4】覆盖了1中元素【4,5,6】 26 | ***********************************************/ 27 | 28 | /********************************************** 29 | 使用切片长时间引用”超大“的底层数组,会导致严重的内存浪费。 30 | 可以新建一个小的切片对象,然后将所需的数据复制过去。函数 31 | copy可以再切片之间复制元素,能够复制的数量取决于复制方和 32 | 被复制方的长度值,通常去最小值。需要注意的是,在同一底层 33 | 数组的不同切片间复制元素时,元素位置会发生重叠。 34 | *********************************************/ 35 | -------------------------------------------------------------------------------- /5数组切片和字典/11.go: -------------------------------------------------------------------------------- 1 | //字典的初始化于创建 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | //字典声明后如果没初始化值为nil 10 | var map1 map[string]int 11 | fmt.Println(map1) 12 | //未初始化map1["Key1"]=1语句编译错误 13 | //使用make创建后就可以给字典增加数据项了 14 | map1=make(map[string]int) 15 | map1["key1"]=1 16 | fmt.Println(map1) 17 | //使用”{}“初始化后也可以给字典增加数据项 18 | var map2=map[string]int{} 19 | map2["key2"]=2 20 | fmt.Println(map2) 21 | } 22 | /************************************* 23 | Map是一种特殊的数据结构,它由一对无序的数据项 24 | 组成,Map通过把键映射到值来进行访问,这加快数 25 | 据的查找速度,所以Map也被称作字典或哈希表。 26 | 字典声明时,除了要定义字典名,还要指定”键“类型 27 | 和”值“类型,键类型要用[]括起来。 28 | var mapName map[keyType]valueType 29 | ************************************/ -------------------------------------------------------------------------------- /5数组切片和字典/12.go: -------------------------------------------------------------------------------- 1 | //字典项查找 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var map1=map[string]int{"key1":100,"key2":200} 10 | //key值存在 11 | v,OK:=map1["key1"] 12 | if OK { 13 | fmt.Println(v,OK) 14 | }else{ 15 | fmt.Println(v) 16 | } 17 | //key值不存在 18 | v,k:=map1["key3"] 19 | if k { 20 | fmt.Println(v,k) 21 | }else{ 22 | fmt.Println(v) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /5数组切片和字典/13.go: -------------------------------------------------------------------------------- 1 | //字典项的删除与增添 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var map1=map[string]int{"key1":100,"key2":200,"key3":300} 10 | //使用range遍历map1的过程中删除和增加字典项 11 | for k,v:=range map1{ 12 | fmt.Println(k,v) 13 | //删除字典项 14 | if k=="key2" { 15 | delete(map1,k) 16 | } 17 | if k=="key3" { 18 | map1["key4"]=400 19 | } 20 | } 21 | fmt.Println(map1) 22 | } -------------------------------------------------------------------------------- /5数组切片和字典/13newmake.go: -------------------------------------------------------------------------------- 1 | //Go中的内存分配new和make 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | fmt.Println("Hello World") 10 | } 11 | /***************************************** 12 | Go有两种分配内存的机制,分别是使用内置函数new() 13 | 和make(),他们所对应的类型不同。 14 | new可以给一个值类型的数据分配内存,返回该类型的 15 | 内存指针,即是返回了一个指向新分配的类型为T的零 16 | 值的指针。 17 | make用于给引用类型分配内存空间,比如像slice, 18 | map,channel等。make返回的是一个对象,而非是一 19 | 个内存空间的指针,分多少内存由该对象的大小和个数 20 | 来决定。 21 | ***************************************** 22 | func new(Type)* Type 23 | func make(Type,size IntegerType) Type 24 | ***************************************** 25 | var p* []int=new([]int) 26 | var v []int=make([]int,10) 27 | var v []int=make([]int,10,10) 28 | ****************************************/ -------------------------------------------------------------------------------- /5数组切片和字典/2.go: -------------------------------------------------------------------------------- 1 | //数组的初始化 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var a [10]int 10 | //定义时对数组元素赋初值 11 | var b=[10]int{1,2,3,4,5,6,7,8,9,10} 12 | //可初始化列表决定数组长度 13 | var c=[]int{1,2,3} 14 | //只给一部分元素赋初值 15 | var d=[10]int{1,2,3,4,5} 16 | //按下标初始化元素 17 | var e=[10]int{2:4,5:7} 18 | fmt.Println(a) 19 | fmt.Println(b) 20 | fmt.Println(c) 21 | fmt.Println(d) 22 | fmt.Println(e) 23 | } -------------------------------------------------------------------------------- /5数组切片和字典/3.go: -------------------------------------------------------------------------------- 1 | //打印Fibonacci数列的前20项 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var f=[20]int{1,1} 10 | for i:=2;i<20;i++{ 11 | f[i]=f[i-2]+f[i-1] 12 | } 13 | for i:=0;i<20;i++ { 14 | if i%5==0{ 15 | fmt.Printf("\n") 16 | } 17 | fmt.Printf("f[%2d]=%4d ",i,f[i]) 18 | } 19 | } 20 | 21 | /********************************************* 22 | 使用range遍历数组 23 | func main(){ 24 | var f=[20]int{1,1} 25 | for i:=2;i<20;i++{ 26 | f[i]=f[i-2]+f[i-1] 27 | } 28 | for i,v:=range f { 29 | if i%5==0{ 30 | fmt.Printf("\n") 31 | } 32 | fmt.Printf("f[%2d]=%4d ",i,v) 33 | } 34 | } 35 | *********************************************/ -------------------------------------------------------------------------------- /5数组切片和字典/4.go: -------------------------------------------------------------------------------- 1 | //二维数组 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var a=[3][4]int{{1,2,3},{4,5},{6}} 10 | fmt.Println(a) 11 | } 12 | /************************************** 13 | 定义多维数组为 14 | var f[3][4][5]float64 15 | **************************************/ -------------------------------------------------------------------------------- /5数组切片和字典/5.go: -------------------------------------------------------------------------------- 1 | //找出二位数组最大元素并输出行号和列号 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var i,j,row,col,max int 10 | var a=[3][4]int{{1,7,3,12},{4,9,5,19},{8,22,6,10}} 11 | max=a[0][0] 12 | for i=0;i<=2;i++{ 13 | for j=0;j<=3;j++{ 14 | if a[i][j]>max{ 15 | max=a[i][j] 16 | row=i 17 | col=j 18 | } 19 | } 20 | } 21 | fmt.Printf("max=%d,row=%d,col=%d\n",max,row,col) 22 | } 23 | /*************************************************** 24 | 在Go语言中数组是一个值类型,所有的值类型变量在赋值或作为参数 25 | 传递时都将产生一次复制动作。将数组作为函数的参数类型,在函数 26 | 调用时该参数将发生数据复制,所以在函数体中无法修改数组的内容。 27 | ***************************************************/ 28 | -------------------------------------------------------------------------------- /5数组切片和字典/6.go: -------------------------------------------------------------------------------- 1 | //基于底层数组创建用户 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | //先定义并初始化底层数组 10 | var array1=[10]int{1,2,3,4,5,6,7,8,9,10} 11 | //注意切片类型和底层数组类型保持一致 12 | var slice1 []int 13 | //部分引用的三种形式 14 | slice1=array1[:5] 15 | slice2:=array1[5:] 16 | slice3:=array1[4:7] 17 | //全部引用的三种形式 18 | slice4:=array1 19 | slice5:=array1[:] 20 | slice6:=array1[0:len(array1)] 21 | fmt.Println(slice1) 22 | fmt.Println(slice2) 23 | fmt.Println(slice3) 24 | fmt.Println(slice4) 25 | fmt.Println(slice5) 26 | fmt.Println(slice6) 27 | } 28 | /**************************************** 29 | 切片的初始化方式(首先定义好数组,在初始化切片) 30 | 切片名=数组名[start:end] 31 | 直接创建切片,即在定义切片的同时初始化切片元素。 32 | var slice1=[]int{1,2,3,4,5} 33 | 好像和初始化数组有些类似呀,只是切片的中括号中 34 | 没有定义数组的长度。 35 | ****************************************/ 36 | 37 | /**************************************** 38 | 在Go中切片(slice)是数组的一个引用,它会生成一个 39 | 指向数组的指针,并通过切片长度关联到底层数组或者全部 40 | 元素。切片通常被用来实现变长数组,而且操作灵活。 41 | ****************************************/ -------------------------------------------------------------------------------- /5数组切片和字典/7.go: -------------------------------------------------------------------------------- 1 | //直接和使用make创建切片 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | //直接创建 10 | var slice1=[]int{1,2,3,4,5} 11 | //使用make创建 12 | var slice2=make([]int,5) 13 | //使用make创建并预留元素存储空间 14 | var slice3=make([]int,5,10) 15 | fmt.Printf("len=%2d cap=%2d %v\n",len(slice1),cap(slice1),slice1) 16 | fmt.Printf("len=%2d cap=%2d %v\n",len(slice2),cap(slice2),slice2) 17 | fmt.Printf("len=%2d cap=%2d %v\n",len(slice3),cap(slice3),slice3) 18 | } -------------------------------------------------------------------------------- /5数组切片和字典/8.go: -------------------------------------------------------------------------------- 1 | //切片元素的遍历 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var slice1=[]int{1,2,3,4,5} 10 | //使用下标访问切片元素 11 | for i:=0;i<=4;i++{ 12 | fmt.Printf("slice1[%d]=%d",i,slice1[i]) 13 | } 14 | fmt.Printf("\n") 15 | //使用range遍历所有元素 16 | for i,v:=range slice1{ 17 | fmt.Printf("slice1[%d]=%d",i,v) 18 | } 19 | } 20 | /************************************************* 21 | 切片元素的遍历和数组元素的遍历一样,要通过元素的下标访问,另外 22 | 也可以使用关键字range遍历所有切片元素。 23 | ************************************************/ -------------------------------------------------------------------------------- /5数组切片和字典/9.go: -------------------------------------------------------------------------------- 1 | //使用append函数增加切片元素 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | //使用make创建切片len=3,cap=6 10 | var slice1=make([]int,3,6) 11 | //使用append给切片增加元素且未超出cap 12 | slice2:=append(slice1,1,2,3) 13 | //使用append给切片增加元素并且超出cap 14 | slice3:=append(slice1,1,2,3,4) 15 | fmt.Printf("len=%d cap=%d %v\n",len(slice1),cap(slice1),slice1) 16 | fmt.Printf("len=%d cap=%d %v\n",len(slice2),cap(slice2),slice2) 17 | fmt.printf("len=%d cap=%d %v\n",len(slice3),cap(slice3),slice3) 18 | } 19 | /***************************************************** 20 | append只是往切片尾部增加元素,如果不超出容量,增加新元素不会改变 21 | 原来切片的属性,如果超出容量,则分配一个是原来容量2倍的新的内存块, 22 | 再复制数据到新的内存块。 23 | ****************************************************/ -------------------------------------------------------------------------------- /6函数/1.go: -------------------------------------------------------------------------------- 1 | //调用时间函数获取当前日期(调用标准函数) 2 | package main 3 | 4 | import( 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | func main(){ 10 | //获取时间戳 11 | t:=time.Now() 12 | //按年 月 日 时 分 秒格式输出 13 | fmt.Println(t.String()) 14 | //按年 月 日格式输出 15 | fmt.Println(t.Format("2006年01月02日")) 16 | //输出星期几 17 | fmt.Println(t.Weekday().String()) 18 | } -------------------------------------------------------------------------------- /6函数/10.go: -------------------------------------------------------------------------------- 1 | //defer语句定义函数延迟执行 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | f1() 10 | f2() 11 | fmt.Printf("\n") 12 | fmt.Println(f3()) 13 | } 14 | //一个延迟执行的函数的变量的值在声明延迟时别赋值 15 | func f1(){ 16 | i:=0 17 | defer fmt.Println(i) 18 | i++ 19 | return 20 | } 21 | //被延迟的函数按照先进后出的顺序执行 22 | func f2(){ 23 | for i:=0;i<4;i++ { 24 | defer fmt.Printf("%d",i) 25 | } 26 | } 27 | //被延迟的匿名函数会读取函数f3的返回值,或对f3的返回值赋值。 28 | func f3()(i int){ 29 | defer func(){ 30 | i++ 31 | }() 32 | return 1 33 | } 34 | /********************************************** 35 | 在Go语言中,defer语句的作用是不管程序时候出现异常,均在 36 | 函数退出时自动执行相关代码。 37 | func main(){ 38 | defer fmt.Println("The first.") 39 | fmt.Println("The second.") 40 | } 41 | 首先输出"The second.",然后才输出"The first."。 42 | **********************************************/ 43 | 44 | /********************************************** 45 | 如果程序中有多个defer语句,则按照”先进后出(FIFO)“的次序 46 | 执行,即最后一个defer语句将最先被执行。 47 | func main(){ 48 | for i:=0;i<5;i++{ 49 | defer fmt.Println(i) 50 | } 51 | } 52 | 输出结果为:4,3,2,1,0。 53 | *********************************************/ 54 | 55 | /********************************************* 56 | 在Go语言中,defer语句还支持匿名函数调用,如果函数有返回 57 | 值,被延迟执行的匿名函数还会读取函数的返回值,并对返回值 58 | 赋值。 59 | *********************************************/ -------------------------------------------------------------------------------- /6函数/11.go: -------------------------------------------------------------------------------- 1 | //defer语句保证文件能够正常关闭 2 | package main 3 | 4 | import( 5 | "fmt" 6 | "os" 7 | "io" 8 | ) 9 | 10 | func main(){ 11 | copylen,err:=copyFile("dis.txt","src.txt") 12 | if err!=nil{ 13 | return 14 | }else{ 15 | fmt.Println(copylen) 16 | } 17 | } 18 | //函数copyFile的功能是将源文件src的数据复制给目标文件dst 19 | func copyFile(dstName,srcName string)(copylen int64,err error){ 20 | src,err:=os.Open(srcName) 21 | if err!=nil { 22 | return 23 | } 24 | //当return时就会调用src.Close()把源文件关闭 25 | defer src.Close() 26 | dst,err:=os.Create(dstName) 27 | if err!=nil{ 28 | return 29 | } 30 | //当return时就会调用src.Close()把目标文件关闭 31 | defer dst.Close() 32 | return io.Copy(dst,src) 33 | } 34 | /******************************************* 35 | 在Go程序中,当程序返回或发生异常时,defer语句通常用来 36 | 做一些函数调用后的清理工作,释放资源变量。 37 | 关闭文件句柄: 38 | srcFile,err:=os.Open("myfile") 39 | defer srcFile.Close() 40 | 关闭互斥锁: 41 | mutex.Lock() 42 | defer mutex.Unlock() 43 | 上面例子中defer语句的用法有两个优点: 44 | 1让设计者永远也不会忘记关闭文件,有时当函数返回时常常 45 | 忘记释放打开的资源变量。 46 | 2将关闭和打开靠在一起,程序的意图也变得清晰很多。 47 | *******************************************/ -------------------------------------------------------------------------------- /6函数/12.go: -------------------------------------------------------------------------------- 1 | //panic-and-recover异常恢复机制 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | //必须要先声明defer,否则捕获不到panic异常 10 | defer func(){ 11 | fmt.Println("函数defer开始运行...") 12 | if err:=recover();err!=nil{ 13 | //这里的err就是panic传入的内容 14 | fmt.Println("程序异常退出:",err) 15 | }else{ 16 | fmt.Println("程序正常退出。") 17 | } 18 | }() 19 | f(101) 20 | } 21 | func f(a int){ 22 | fmt.Println("函数f开始运行...") 23 | if a>100 { 24 | panic("参数值超出范围!") 25 | }else{ 26 | fmt.Println("函数f调用结束。") 27 | } 28 | } 29 | /******************************************* 30 | panic是内置函数,可以中断原有的控制流程,进入一个异常 31 | 流程中。 32 | recover也是一个内置的函数,他可以进入异常流程中的 33 | goroutine恢复过来。recover仅在延迟函数中有效。在正常 34 | 的执行过程中,调用recover会返回nil并且没有其他任何效果 35 | 。如果goroutine陷入异常,调用recover可以捕获到panic 36 | 的输入值,并且恢复正常的执行。 37 | *******************************************/ -------------------------------------------------------------------------------- /6函数/13.go: -------------------------------------------------------------------------------- 1 | //函数嵌套调用求最小公倍数 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var a,b,c int 10 | fmt.Println("请输入正整数a和b:") 11 | fmt.Scanf("%d,%d",&a,&b) 12 | c=multiple(a,b) 13 | fmt.Printf("正整数%d和%d的最小公倍数为%d。\n",a,b,c) 14 | } 15 | /* 16 | 函数divisor()的功能是求最大公约数 17 | */ 18 | func divisor(a,b int) int { 19 | var r int 20 | for{ 21 | r=a%b 22 | if r!=0 { 23 | a=b 24 | b=r 25 | }else{ 26 | break 27 | } 28 | } 29 | return b 30 | } 31 | /* 32 | 函数multipel()的功能是求最小公约数 33 | */ 34 | func multiple(a,b int) int { 35 | var d int 36 | d=divisor(a,b) 37 | return(a*b/d) 38 | } -------------------------------------------------------------------------------- /6函数/14.go: -------------------------------------------------------------------------------- 1 | //使用变参函数求最小数 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | min:=Min(12,3,24,7) 10 | fmt.Println("最小数为:",min) 11 | arr:=[]int{-6,13,7,25,-13} 12 | min=Min(arr...) 13 | fmt.Println("数组中的最小数为:",min) 14 | } 15 | /* 16 | 函数Min()的功能是找出最小数 17 | */ 18 | func Min(a ...int) int { 19 | if len(a)==0{ 20 | return 0 21 | } 22 | min:=a[0] 23 | for _,v:=range a{ 24 | if v='0' && b[i]<='9'{ 31 | start=true 32 | } 33 | for ;i='0' && b[i]<='9'{ 35 | if start==false { 36 | index=1 37 | break 38 | }else{ 39 | x=x*10+int(b[i])-'0' 40 | } 41 | }else if b[i]<'0'||b[i]>'9'{ 42 | start=false 43 | } 44 | } 45 | return index,x 46 | } -------------------------------------------------------------------------------- /6函数/2.go: -------------------------------------------------------------------------------- 1 | //自定义函数的声明与调用(调用自定义函数) 2 | package main 3 | 4 | import( 5 | "fmt" 6 | "errors" 7 | ) 8 | 9 | //函数f1()无参数且无返回值 10 | func f1(){ 11 | fmt.Println("Hello World!") 12 | } 13 | //函数f2()有参数但无返回值 14 | func f2(a,b int,c string){ 15 | fmt.Println(a,b,c) 16 | } 17 | //函数f3()有一个返回值 18 | func f2(a,b int) int { 19 | return a+b 20 | } 21 | //函数f4()有两个返回值 22 | func f4(a,b int)(ret float32,err error){ 23 | if b==0 { 24 | err=errors.New("Overflow!") 25 | return 26 | }else{ 27 | return float32(a)/float32(b),nil 28 | } 29 | } 30 | func main(){ 31 | var a,b int=2,3 32 | var c string="Golang" 33 | f1() 34 | f2(a,b,c) 35 | sum:=f3(a,b) 36 | fmt.Println(sum) 37 | f,err:=f4(a,b) 38 | fmt.Println(f,err) 39 | } -------------------------------------------------------------------------------- /6函数/3.go: -------------------------------------------------------------------------------- 1 | //调用mymath包中的函数 2 | package main 3 | 4 | import( 5 | "fmt" 6 | //导入mymath包 7 | "mymath" 8 | ) 9 | 10 | func main(){ 11 | var a,b int=2,3 12 | add:=mymath.Add(a,b) 13 | fmt.Println(add) 14 | sub:=mymath.Sub(a,b) 15 | fmt.Println(sub) 16 | mult:=mymath.Mult(a,b) 17 | fmt.Println(mult) 18 | div:=mymath.Div(a,b) 19 | fmt.Println(div) 20 | } -------------------------------------------------------------------------------- /6函数/4.go: -------------------------------------------------------------------------------- 1 | //变参函数的声明 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | f1(1,2,3) 10 | f1(1,2,3,4,5) 11 | } 12 | //声明函数f1()为变参函数 13 | func f1(args ... int){ 14 | //变参args其实质是一个切片 15 | fmt.Println(args) 16 | } 17 | /***************************************** 18 | Go语言支持不定长变参,但是要注意不定长变参只能作为 19 | 函数的最后一个参数,不能放在其他参数的前面。 20 | 变参的定义格式为"... 类型",而且变参必须是函数的最后 21 | 一个参数,例如:func f1(a int,s string,args ...int){} 22 | 不定长变参其实质就是一个切片,可以使用range进行遍历 23 | func f1(args ...int){ 24 | for _,arg:=range args{ 25 | fmt.Println(arg) 26 | } 27 | } 28 | ****************************************/ 29 | -------------------------------------------------------------------------------- /6函数/5.go: -------------------------------------------------------------------------------- 1 | //变参的传递 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | f1(1,2,3,4,5) 10 | } 11 | //声明函数f1(),f2()为变参函数 12 | func f1(args ...int){ 13 | //全部传递,即将函数f1()的args直接复制给函数f2() 14 | f2(args ...) 15 | //部分传递,将args中的第3个以后的元素复制给函数f2() 16 | f2(args[2:]...) 17 | } 18 | func f2(args ...int){ 19 | fmt.Println(args) 20 | } -------------------------------------------------------------------------------- /6函数/6.go: -------------------------------------------------------------------------------- 1 | //任意类型的变参 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | f1(2,"Go",8,"Language",'a',false,'A',3,14) 10 | } 11 | //声明函数f1()为任意类型变参 12 | func f1(args ...interface{}){ 13 | var num=make([]int,0,6) 14 | var str=make([]string,0,6) 15 | var ch=make([]int32,0,6) 16 | var other=make([]interface{},0,6) 17 | for _,arg:=range args{ 18 | switch v:=arg.(type){ 19 | case int: 20 | num=append(num,v) 21 | case string: 22 | str=append(str,v) 23 | case int32: 24 | ch=append(ch,v) 25 | default: 26 | other=append(other,v) 27 | } 28 | } 29 | fmt.Println(num) 30 | fmt.Println(str) 31 | fmt.Println(ch) 32 | fmt.Println(other) 33 | } 34 | /**************************************** 35 | 在Go语言中,空接口interface{}可以指向任何数据对 36 | 象,所以可以使用interfa{}定义任意类型变参。同时, 37 | interfa()也是类型安全的。 38 | Go语言规定,如果希望传递任意类型的变参,变参类型应 39 | 指定为空接口interfac{} 40 | ****************************************/ -------------------------------------------------------------------------------- /6函数/7.go: -------------------------------------------------------------------------------- 1 | //匿名函数的声明与调用 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | //声明并直接将匿名函数赋值给变量f 10 | f:=func(a,b int) int { 11 | return a+b 12 | } 13 | //对函数类型变量f进行调用 14 | sum:=f(2,3) 15 | fmt.Println(sum) 16 | //声明并直接执行匿名函数 17 | sum=func(a,b int) int { 18 | return a+b 19 | }(5,7) 20 | fmt.Println(sum) 21 | } 22 | /*************************************** 23 | 在Go语言中,所有的函数都是值类型,可以作为参数传递。 24 | 可以随意对匿名函数变量进行传递和调用。 25 | 匿名函数由一个不带函数名的函数声明和函数体组成,如下 26 | 所示: func (参数列表) 返回值{ 函数体 }。 27 | 匿名函数在声明的同时可以直接执行。 28 | 在Go语言中,使用匿名函数时注意不能作为顶级函数,而 29 | 只能放在其他函数的函数体中,也就是说它必须有一个外 30 | 层函数。 31 | ***************************************/ -------------------------------------------------------------------------------- /6函数/8.go: -------------------------------------------------------------------------------- 1 | //函数的闭包 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | f:=closures(10) 10 | fmt.Println(f(1)) 11 | fmt.Println(f(2)) 12 | } 13 | //注意函数的闭包返回值是匿名函数 14 | func closures(x int) func(int) int{ 15 | return func(y int) int{ 16 | //注意内部函数引用的参数超出了它的作用范围 17 | return x+y 18 | } 19 | } 20 | /******************************************* 21 | 函数闭包的两个作用: 22 | 1函数闭包可以保护函数内的变量安全。 23 | 2函数闭包可以在内存中维持一个变量。 24 | *******************************************/ -------------------------------------------------------------------------------- /6函数/9.go: -------------------------------------------------------------------------------- 1 | //函数的递归调用 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | func main(){ 9 | var result int=0 10 | for i:=0;i<20;i++{ 11 | result=fibonacci(i) 12 | if i%5==0{ 13 | fmt.Printf("\n") 14 | } 15 | fmt.Printf("%4d",result) 16 | } 17 | } 18 | //fibonacci()函数递归调用 19 | func fibonacci(n int)(res int){ 20 | if n<=1 { 21 | res=1 22 | }else{ 23 | res=fibonacci(n-1)+fibonacci(n-2) 24 | } 25 | return 26 | } -------------------------------------------------------------------------------- /6函数/Go闭包.go: -------------------------------------------------------------------------------- 1 | //golang闭包实例 2 | import ( 3 | "fmt" 4 | ) 5 | 6 | func Func() (func(), func()) { 7 | i := 10 8 | return func() { 9 | i++ 10 | }, func() { 11 | fmt.Println(i) 12 | } 13 | } 14 | 15 | func main() { 16 | Add, Print := Func() 17 | 18 | for i := 0; i < 10; i++ { 19 | Add() 20 | } 21 | 22 | Print() 23 | } -------------------------------------------------------------------------------- /6函数/mymath.go: -------------------------------------------------------------------------------- 1 | /****************************************** 2 | mymath包实现加减乘除四则运算。 3 | 加法运算:Add()函数。 4 | 减法运算:Sub()函数。 5 | 乘法运算:Mult()函数。 6 | 除法运算:Div()函数。 7 | *******************************************/ 8 | package mymath 9 | 10 | func Add(a,b int) int { 11 | return a+b 12 | } 13 | 14 | func Sub(a,b int) int { 15 | return a-b 16 | } 17 | 18 | func Mult(a,b int) int { 19 | return a*b 20 | } 21 | 22 | func Div(a,b int) float32{ 23 | if b!=0 { 24 | return float32(a)/float32(b) 25 | }else{ 26 | return 0 27 | } 28 | } -------------------------------------------------------------------------------- /7结构体和方法/1.go: -------------------------------------------------------------------------------- 1 | //结构体的定义与简单操作 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | type student struct{ 9 | id int 10 | name string 11 | sex bool 12 | age int 13 | class string 14 | } 15 | 16 | func main(){ 17 | //标准方式定义 18 | var stu1 student 19 | //简写方式定义 20 | stu2:=student{} 21 | stu1.name="李明" 22 | stu2.name="张衡" 23 | stu1.age=18 24 | stu2.age=19 25 | fmt.Println(stu1) 26 | fmt.Println(stu2) 27 | } 28 | /******************************************* 29 | 在Go语言中,可以使用关键词"type"定义新的数据类型,每个 30 | 结构体中属于一个新的数据类型,结构体中的数据项,通常被称 31 | 为字段(field),在定义结构体必须使用type关键字和关键 32 | 字struct。 33 | type 结构体名 struct { 34 | field1 类型 35 | ..... 36 | } 37 | 结构体中只有首写字母为大写的结构体和属性才能在包外被访问。 38 | 结构体中的预留字段:(在Go语言中,预留字段使用"_"来命名) 39 | type people struct{ 40 | name string 41 | age int 42 | _ string 43 | } 44 | 在Go语言中,结构体中本身也是一种数据类型,所以也可以使用 45 | 结构体作为字段的类型。 46 | type date string{ 47 | year int 48 | month int 49 | day int 50 | } 51 | type student struct{ 52 | id int 53 | name string 54 | sex bool 55 | class string 56 | birthday date 57 | } 58 | 结构体变量的声明和声明普通变量一样,使用var来定义。 59 | var stu student 60 | 在进行结构体变量声明时,通常使用":="简写的方式。 61 | stu:=student{} 62 | 结构体中字段的访问使用"."操作符。 63 | stu.name="李明" 64 | stu.age=18 65 | *******************************************/ 66 | 67 | /******************************************* 68 | Go语言规定:int型的类型零值为0,bool型的类型零值为 69 | false,string型的类型零值为空字符串。 70 | *******************************************/ -------------------------------------------------------------------------------- /7结构体和方法/10.go: -------------------------------------------------------------------------------- 1 | //同名字段的隐藏 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | type people struct{ 9 | name string 10 | sex bool 11 | phone string //重名字段 12 | } 13 | 14 | type teacher struct{ 15 | people 16 | department string 17 | phone string //重名字段 18 | } 19 | 20 | func main(){ 21 | teacher1:=teacher{people{"郑智",false,"100-201"},"Computer Science","200-401"} 22 | //外部字段隐藏了匿名字段同名成员 23 | fmt.Println(teacher1.phone) 24 | //通过匿名字段类型前缀访问被嵌入的同名字段 25 | fmt.Println(teacher1.people.phone) 26 | } 27 | /*************************************************** 28 | 如果多个匿名字段同一层次重名,就要使用匿名字段类型前缀访问。 29 | fmt.Println(d.d1.x,d.d2.x) 30 | ***************************************************/ -------------------------------------------------------------------------------- /7结构体和方法/11.go: -------------------------------------------------------------------------------- 1 | //通过匿名字段类型前缀访问同层的同名字段 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | type d1 struct{ 9 | x int 10 | } 11 | type d2 struct{ 12 | x int 13 | } 14 | type data struct{ 15 | d1 16 | d2 17 | } 18 | 19 | func main(){ 20 | d:=data{d1{10},d2{20}} 21 | fmt.Println(d.d1.x,d.d2.x) 22 | } -------------------------------------------------------------------------------- /7结构体和方法/12.go: -------------------------------------------------------------------------------- 1 | //匿名类型指针 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | type people struct{ 9 | name string 10 | sex bool 11 | } 12 | 13 | type teacher struct{ 14 | *people //匿名类型指针 15 | department string 16 | } 17 | func main(){ 18 | teacher1:=teacher{&people{"郑智",false},"Computer Science"} 19 | //匿名类型指针访问和普通名字段访问方式相同 20 | fmt.Println(teacher1,teacher1.name,teacher1.department) 21 | } -------------------------------------------------------------------------------- /7结构体和方法/13.go: -------------------------------------------------------------------------------- 1 | //Method的基本定义 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | type rectangle struct{ 9 | width int 10 | height int 11 | } 12 | //函数area()是对象rectangle的一个方法 13 | func (recv rectangle) area() int { 14 | return recv.width*recv.height 15 | } 16 | func main(){ 17 | r1:=rectangle{4,3} 18 | r2:=rectangle{30,15} 19 | fmt.Println(r1.area(),r2.area()) 20 | } 21 | /******************************************** 22 | Go语言的Method(方法)类似于一个函数,只是函数名前多了 23 | 个绑定类型参数receiver。 24 | func (recv recviver_type) methodName(参数列表)(返回值){ 25 | ...... 26 | } 27 | Method中的Receiv可以是内置类型,自定义类型,结构体 28 | 或指针类型。 29 | ******************************************/ -------------------------------------------------------------------------------- /7结构体和方法/14.go: -------------------------------------------------------------------------------- 1 | //多个Method可以同名 2 | package main 3 | 4 | import( 5 | "fmt" 6 | // "math" 7 | ) 8 | /* 9 | type rectangle struct{ 10 | width int 11 | height int 12 | } 13 | type circle struct{ 14 | radius float32 15 | } 16 | //此处area()是对象rectangle的一个方法 17 | func (recv rectangle) area() int { 18 | return recv.width*recv.height 19 | } 20 | //此处area()是对象circle的一个方法 21 | func (recv circle) area() float32{ 22 | return recv.radius*recv.radius*math.Pi 23 | } 24 | func main(){ 25 | r1:=rectangle{4,3} 26 | c1:=circle{5} 27 | fmt.Println(r1.area(),c1.area()) 28 | } 29 | */ 30 | /****************************************** 31 | 如果普通类型作为receiver,他只是一个值传递,而指针类 32 | 型作为receive,他将是一个引用传递。两者的差别在于, 33 | 指针会对实例对象的内容发生操作,而普通类型仅是以副本作 34 | 为操作对象。 35 | Method的名字一样,但如果接受者不一样,那method就不 36 | 一样。 37 | Method里面可以访问接受者的字段,调用Method进行访问, 38 | 就像在struct里访问字段一样。 39 | ******************************************/ 40 | 41 | /* 42 | type coordinate struct { 43 | x int 44 | y int 45 | } 46 | func (recv coordinate) swap(){ 47 | var temp int 48 | temp,recv.x,recv.y=temp,recv.y,recv.x 49 | fmt.Println(recv) 50 | } 51 | func main(){ 52 | r1:=coordinate{3,4} 53 | r1.swap() 54 | fmt.Println(r1) 55 | } 56 | */ 57 | 58 | type coordinate struct { 59 | x int 60 | y int 61 | } 62 | func (recv* coordinate) swap(){ 63 | var temp int 64 | temp,recv.x,recv.y=temp,recv.y,recv.x 65 | fmt.Println(recv) 66 | } 67 | func main(){ 68 | r1:=coordinate{3,4} 69 | p:=&r1 70 | p.swap() 71 | fmt.Println(r1) 72 | } -------------------------------------------------------------------------------- /7结构体和方法/15.go: -------------------------------------------------------------------------------- 1 | //匿名Recevier 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | type object struct{ 9 | id int 10 | name string 11 | } 12 | 13 | func (object) msgbox(){ 14 | fmt.Println("This is a object!") 15 | } 16 | func (*object) msgBox(){ 17 | fmt.Println("This is a object!") 18 | } 19 | 20 | func main(){ 21 | obj:=object{} 22 | p:=&obj 23 | obj.msgbox() 24 | p.msgBox() 25 | } 26 | /*************************************** 27 | 如果方法代码中从不使用Receiver参数,那么就可以省 28 | 略Receiver的变量名,此时的接受者将是一个匿名 29 | Receiver。 30 | ***************************************/ -------------------------------------------------------------------------------- /7结构体和方法/16.go: -------------------------------------------------------------------------------- 1 | //Method的继承 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | type people struct{ 9 | name string 10 | phone string 11 | } 12 | type teacher struct{ 13 | people 14 | department string 15 | } 16 | type student struct{ 17 | people 18 | school string 19 | } 20 | 21 | func (r people) sayHi(){ 22 | fmt.Printf("Hi,I'm %s you can call me on %s.\n",r.name,r.phone) 23 | } 24 | 25 | func main(){ 26 | teacher1:=teacher{people{"郑智","010-22002"},"Computer Science"} 27 | student1:=student{people{"李明","010-11001"},"Yale University"} 28 | teacher1.sayHi() 29 | student1.sayHi() 30 | } 31 | /**************************************** 32 | people作为teacher和student的匿名字段,sayHi是 33 | 为people实现的一个方法。作为外层的结构,teacher 34 | 和student同时也继承了people所拥有的方法,所以在 35 | teacher和student的对象中可以直接调用方法sayHi() 36 | ****************************************/ -------------------------------------------------------------------------------- /7结构体和方法/17.go: -------------------------------------------------------------------------------- 1 | //Method的重写 2 | package main 3 | 4 | import( 5 | "fmt" 6 | ) 7 | 8 | type people struct{ 9 | name string 10 | phone string 11 | } 12 | type teacher struct{ 13 | people 14 | department string 15 | } 16 | type student struct{ 17 | people 18 | school string 19 | } 20 | 21 | func (r people) sayHi(){ 22 | fmt.Printf("Hi,I'm %s you can call me on %s.\n",r.name,r.phone) 23 | } 24 | func (s student) sayHi(){ 25 | fmt.Printf("Hi,I'm %s.I study in %s,call me on %s.\n",s.name,s.school,s.phone) 26 | } 27 | 28 | func main(){ 29 | teacher1:=teacher{people{"郑智","010-22002"},"Computer Science"} 30 | student1:=student{people{"李明","010-11001"},"Yale University"} 31 | teacher1.sayHi() 32 | student1.sayHi() 33 | } -------------------------------------------------------------------------------- /7结构体和方法/18.go: -------------------------------------------------------------------------------- 1 | //Struct的导入 2 | package main 3 | 4 | import( 5 | "fmt" 6 | "mystruct" 7 | ) 8 | 9 | func main(){ 10 | usr:=new(mystruct.User) 11 | usr.Id=100 12 | usr.Name="张三" 13 | usr.SayHi() 14 | fmt.Println(usr) 15 | } 16 | /*************************************** 17 | Go语言中要使包内的某个标示符对其他包可见,该标示 18 | 符的首写字母必须大写,这就是Go语言的可见性规则。 19 | ***************************************/ -------------------------------------------------------------------------------- /7结构体和方法/18mystruct.go: -------------------------------------------------------------------------------- 1 | /*********************************** 2 | mystruct包定义了User对象,并实现了两个对 3 | User进行操作的方法。 4 | SayHi()方法 5 | old()方法 6 | ***********************************/ 7 | package mystruct 8 | 9 | import ( 10 | "fmt" 11 | ) 12 | 13 | type User struct{ 14 | Id int 15 | Name string 16 | age int 17 | } 18 | 19 | func (u* User) SayHi(){ 20 | fmt.Printf("Hi,I'm %s.Nice to meet you!",u.Name) 21 | } 22 | 23 | func (u User) old() int { 24 | return u.age 25 | } -------------------------------------------------------------------------------- /7结构体和方法/19.go: -------------------------------------------------------------------------------- 1 | //字段标签 2 | package main 3 | 4 | import( 5 | "fmt" 6 | "reflect" 7 | ) 8 | 9 | type user struct{ 10 | Id int "账号" 11 | Name string "姓名" 12 | Sex bool "性别" 13 | } 14 | 15 | func main(){ 16 | u:=user{100,"张三",true} 17 | //使用TypeOf()函数获取对象的类型 18 | t:=reflect.TypeOf(u) 19 | //使用ValueOf()获取对象的值 20 | v:=reflect.ValueOf(u) 21 | for i:=0;iimport pkg1-->pkg1(package)-->import pkg2--> 13 | pkg2(package)-->import pkg3-->pkg3(package)-->pkg3-->const... 14 | (p3)-->var...(p3)-->init()(p3)-->const...(p2)-->var...(p2)--> 15 | init()(p2)-->const...(p1)-->var...(p1)-->init()(p1)-->const... 16 | (main)-->var...(main)-->init()(main)-->main()-->Exit 17 | 18 | 下面为被导入包的视图: 19 | 20 | +-------------+ 21 | ------>main | +-------------+ 22 | | import pkg1---------->pkg1 | +-------------+ 23 | | const...<----, | import pkg2---------->pkg2 | +-------------+ 24 | | | | | | const...<----, | import pkg3---------->pkg3 | 25 | | v | | | | | | | const...<----, | | | 26 | | var... | | | v | | | | | | | const... | 27 | | | | | | var... | | | v | | | | | 28 | | v | | | | | | | var... | | | v | 29 | | init() | | | v | | | | | | | var... | 30 | | | | '------init() | | | v | | | | | 31 | | v | | | '------init() | | | v | 32 | | main() | | | | | '------init() | 33 | +------|------+ +-------------+ +-------------+ +-------------+ 34 | v 35 | Exit 36 | ============================================================== 37 | 38 | -------------------------------------------------------------------------------- /Go语言技巧/c.函数作为值和类型: -------------------------------------------------------------------------------- 1 | =============================================================== 2 | 在Go语言中函数也是一种变量,我们可以通过type来定义它,它的类型 3 | 就是所有拥有相同的参数,相同的返回值。 4 | type typename func(input1 inputType1,input2 inputType2 [,...]) 5 | (result1 resultType1 [,...]) 6 | 函数作为类型的好处就是可以把这个类型的函数当做值来传递。 7 | =============================================================== 8 | package main 9 | import (....) 10 | 11 | type testInt func(int) bool //声明了一个函数类型 12 | 13 | func isOdd(integer int) bool ( 14 | ...... 15 | ) 16 | 17 | func isEven(integer int) bool ( 18 | ...... 19 | ) 20 | 21 | //声明的函数类型在这里当做了一个参数 22 | func filter(slice []int,f testInt) []int { 23 | ...... 24 | ) 25 | 26 | func main(){ 27 | ...... 28 | odd:=filter(slice,isOdd) //函数当做值来传递了 29 | ...... 30 | even:=filter(slice,isEven) //函数当做值来传递了 31 | ...... 32 | } 33 | ******************************************************** 34 | 函数当做值和类型的时候在我们写一些通用接口的时候非常有用 35 | ============================================================= 36 | -------------------------------------------------------------------------------- /Go语言技巧/f.gdb-golang: -------------------------------------------------------------------------------- 1 | ============================================================================= 2 | 在使用Go工具go build时,传递-gcflag "-N -l"参数,可以忽略Go语言内部做的一些优 3 | 化,如聚合变量和函数等优化,如果不加这样的参数编译出来的是优化过的程序,这样 4 | 对用GDB来调试程序时是很困难的,所以用GDB调试Go语言程序时要用Go语言的工具进行 5 | 编译(go build -gcflag "-N -l")以便于调试。 6 | ============================================================================= 7 | GDB常用命令 8 | =========== 9 | *list 10 | 简写命令l,用来显示源代码,默认显示十行代码。后面可以带上参数显示具体的行。 11 | *break 12 | 简写命令b,用来设置断点,后面跟上参数设置断点的行数。 13 | *delete 14 | 简写命令d,用来删除断点,后面跟上断点的序号,这个序号可以通过info breakpoints 15 | 获取相应的设置的断点序号。 16 | *backtrace 17 | 简写命令bt,用来打印执行的代码过程。 18 | *info 19 | info命令用来显示信息,后面有几种参数。 20 | 1.info locals 21 | 显示当前执行的程序中的变量值。 22 | 2.info breakpoints 23 | 显示当前设置的断点列表。 24 | 3.info goroutines 25 | 显示当前执行的goroutine列表,带*的表示当前执行。 26 | *print 27 | 简写命令p,用来打印变量或者其他信息,后面跟上需要打印的变量名,还有一些很有用 28 | 的函数$len()和$cap(),用来返回当前string slices或者maps的长度和容量。 29 | *whatis 30 | 用来显示当前变量的类型,后面跟上变量名。 31 | *next 32 | 简写命令n,用来单步调试,跳到下一步,当有断点之后,可以输入n跳转到下一步继续 33 | 执行。 34 | *coutinue 35 | 简写命令c,用来跳出当前断点处,后面可以跟参数N,跳过多少次断点。 36 | *set variable 37 | 该命令用来改变运行过程中的变量值,格式如:set variable = 38 | ============================================================================= 39 | package main 40 | 41 | import ( 42 | "fmt" 43 | "time" 44 | ) 45 | 46 | func counting(c chan<- int) { 47 | for i := 0; i < 10; i++ { 48 | time.Sleep(2 * time.Second) 49 | c <- i 50 | } 51 | close(c) 52 | } 53 | 54 | func main() { 55 | msg := "Starting main" 56 | fmt.Println(msg) 57 | bus := make(chan int) 58 | msg = "starting a gofunc" 59 | go counting(bus) 60 | for count := range bus { 61 | fmt.Println("count:", count) 62 | } 63 | } 64 | ========================================= 65 | go build -gcflags "-N -l" gdbfile.go 66 | gdb gdbfile 67 | run 68 | b 23 69 | list 70 | info locals 71 | p bus 72 | c 73 | c 74 | info locals 75 | info locals 76 | c 77 | info goroutines 78 | goroutine 1 bt 79 | ============================================================================= 80 | 81 | -------------------------------------------------------------------------------- /Go语言技巧/i.go-error: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | Go语言使用一个独立的明确的返回值来传递错误信息的。这与使用异常的Java和Ruby以及 3 | 在C语言中经常见到的超重的单返回值/错误值相比,Go语言的处理方式能清楚的知道哪 4 | 个函数返回了错误,并能像调用那些没有出错的函数一样调用。 5 | ============================================================================== 6 | 按照惯例,错误通常是最后一个返回值并且是error类型,一个内建的接口。 7 | errors.New构造一个使用给定的错误信息的基本error值。 8 | 返回错误值为nil代表没有错误。 9 | 注意在if行中的错误检查代码,在Go中是一个普遍的用法。 10 | 如果想在程序中使用一个自定义错误类型中的数据,需要通过类型断言来得到这个错误类 11 | 型的实例。 12 | ============================================================================== 13 | package main 14 | 15 | import ( 16 | "errors" 17 | "fmt" 18 | ) 19 | 20 | func f1(arg int)(int,error) { 21 | if arg == 42 { 22 | return -1,errors.New("can't work with 42") 23 | } 24 | return arg + 3,nil 25 | } 26 | 27 | type argError struct { 28 | arg int 29 | prob string 30 | } 31 | 32 | func (e *argError) Error() string { 33 | return fmt.Sprintf("%d-%s",e.arg,e.prob) 34 | } 35 | 36 | func f2(arg int)(int,error) { 37 | if arg == 42 { 38 | return -1,&argErro{arg,"can't work with it"} 39 | } 40 | return arg + 3,nil 41 | } 42 | 43 | func main() { 44 | for _,i := range []int{7,42} { 45 | if r,e := f1(i); e != nil { //通常在if行内进行错误检查代码 46 | fmt.Println("f1 failed:",e) 47 | } else { 48 | fmt.Println("f1 worked:",r) 49 | } 50 | for _,i := range []int{7,42} { 51 | if r,e := f2(i);e != nil { //通常在if行内进行错误检查代码 52 | fmt.Println("f2 failed:",e) 53 | } else { 54 | fmt.Println("f2 worked:",r) 55 | } 56 | } 57 | _,e := f2(42) 58 | if ae,ok := e.(*argError); ok { //通过类型断言来得到自定义错误类型 59 | fmt.Println(ae.arg) 60 | fmt.Println(ae.prob) 61 | } 62 | } 63 | ============================================================================== 64 | ============================================================================== 65 | -------------------------------------------------------------------------------- /Go语言技巧/l.go定时器: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | 常常需要在后面一个时刻运行Go代码,或者在某段时间间隔内重复运行。Go的内置定时器 3 | 和打点器特性让这很容易实现。 4 | time.Sleep()用来进行单纯的等待。 5 | time.NewTimer()这个就是一个定时器,它表示在未来某一时刻的独立事件,它将提供一 6 | 个用于通知的通道。 7 | time.NewTimer().C这个是定时器的通道。 8 | <-time.NewTimer().C用于定时器的通道在明确发送了定时器失效之前将一直阻塞。 9 | time.NewTimer().Stop()用于在定时器失效之前(即通道发送通知之前)取消这个定时器 10 | ---------------------------- 11 | package main 12 | 13 | import ( 14 | "time" 15 | "fmt" 16 | ) 17 | 18 | func main() { 19 | //定时器表示在未来某一时刻的独立事件。告诉定时器需要等待的时间,然后 20 | //它将提供一个用于通知的通道。 21 | time1 := timeNewTimer(time.Second * 2) 22 | //直到这个定时器的通道C明确的发送了定时器失效的值之前,将一直阻塞。 23 | <-timer1.C 24 | fmt.Println("Timer 1 expired") 25 | 26 | //定时器失效之前可以取消这个定时器 27 | timer2 := time.NewTimer(time.Second) 28 | go func() { 29 | <-timer2.C 30 | fmt.Println("Timer 2 expired") 31 | }() 32 | stop2 := timer2.Stop() 33 | if stop2 { 34 | fmt.Println("Timer 2 stopped") 35 | } 36 | } 37 | ============================================================================== 38 | ============================================================================== 39 | -------------------------------------------------------------------------------- /Go语言技巧/m.go打点器: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | 定时器是想要在未来某一刻执行一次时使用的。打点器则是想要在固定的时间间隔重复执 3 | 行准备的。定时器(NewTimer) 打点器(NewTicker) 4 | 打点器和定时器的机制有点相似:一个通道用来发送数据。 5 | time.NewTicker() 打点器 6 | time.NewTicker().C 打点器通道 7 | <-time.NewTicker().C 打点器在间隔的时间内阻塞 8 | range time.NewTicker().C 可以迭代打点器的打点时间 9 | time.NewTicker().Stop() 停止打点器 10 | time.Sleep() 时间等待 11 | ------------------------------------ 12 | package main 13 | 14 | import ( 15 | "time" 16 | "fmt" 17 | ) 18 | 19 | func main() { 20 | ticker := time.NewTicker(time.Millisecond * 500) 21 | go func() { 22 | for t := range ticker.C { 23 | fmt.Println("Tick at",t) 24 | } 25 | }() 26 | 27 | time.Sleep(time.Millisecond * 1500) 28 | ticker.Stop() 29 | fmt.Println("Ticker stopped") 30 | } 31 | ============================================================================== 32 | ============================================================================== 33 | -------------------------------------------------------------------------------- /Go语言技巧/n.go工作池: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | 使用Go协程和通道实现一个工作池。 3 | -------------------------------- 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "time" 9 | ) 10 | 11 | //工作池 12 | func worker(id int,jobs <-chan int,results chan<- int) { 13 | for j := range jobs { 14 | fmt.Println("worker",id,"processing job",j) 15 | time.Sleep(time.Second) 16 | results <-j*2 17 | } 18 | } 19 | 20 | func main() { 21 | jobs := make(chan int,100) 22 | results := make(chan int,100) 23 | 24 | //启动了3个worker,初始是阻塞的,由于还没有传递任务 25 | for w := 1;w <= 3;w++ { 26 | go worker(w,jobs,results) 27 | } 28 | 29 | //发送9个jobs,然后close这些通道来表示这些就是所有的任务了 30 | for j := 1;j <= 9;j++ { 31 | jobs <- j 32 | } 33 | close(jobs) 34 | 35 | //最后收集所有这些任务的返回值 36 | for a := 1;a <= 9;a++ { 37 | <-results 38 | } 39 | } 40 | 41 | 整个程序处理所有的任务仅执行了3s而不是9s,因为3个worker是并行的。 42 | ============================================================================== 43 | ============================================================================== 44 | -------------------------------------------------------------------------------- /Go语言技巧/o.go速率限制: -------------------------------------------------------------------------------- 1 | ============================================================================= 2 | 速率限制是一个重要的控制服务资源利用和质量的途径。 3 | Go通过Go协程,通道和打点器优美的支持了速率限制。 4 | -------------------------- 5 | package main 6 | 7 | import ( 8 | "time" 9 | "fmt" 10 | ) 11 | 12 | func main() { 13 | 14 | //====================================================== 15 | //请求限制 16 | requests := make(chan int,5) 17 | for i := 1; i <= 5; i++ { 18 | requests <- i 19 | close(requests) 20 | 21 | //打点器,注意这个返回的本身就是channel 22 | limiter := time.Tick(time.Millisecond * 200) 23 | 24 | //通过<-limiter来丢值在打点器的打点时刻解除阻塞 25 | for req := range requests { 26 | <-limiter 27 | fmt.Println("request",req,time.Now()) 28 | } 29 | 30 | 31 | //=================================================================== 32 | //有时候想临时进行速率限制,并且不影响整体的速率控制,可以通过通道缓冲 33 | //来实现,这个burstyLimiter通道用来进行3次临时的脉冲型速率限制。 34 | burstyLimiter := make(chan time.Time,3) 35 | 36 | //将通道填充临时改变的值 37 | for i := 0; i < 3; i++ { 38 | burstyLimiter <- time.Now() 39 | } 40 | 41 | //每200ms将添加一个新的值到burstyLimiter中,直到达到3个的限制 42 | go func() { 43 | for t := range time.Tick(time.Millisecond * 200) { 44 | burstyLimiter <- t 45 | } 46 | }() 47 | 48 | //--------------------------------------------------------------------- 49 | //现在模拟超过5个接入请求,它们中刚开始的3个将受burstyLimiter的脉冲影响 50 | burstyRequests := make(chan int,5) 51 | for i := 1; i <= 5; i++ { 52 | burstyRequests <- i 53 | } 54 | close(burstyRequests) 55 | for req := range burstyRequests { 56 | //通过通道丢弃值来解除阻塞 57 | <-burstyLimiter 58 | fmt.Println("request",req,time.Now()) 59 | } 60 | } 61 | ============================================================================= 62 | ============================================================================= 63 | -------------------------------------------------------------------------------- /Go语言技巧/p.go原子计数器: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | sync/atomic包在多个Go协程中进行原子计数。 3 | ---------------------------------------- 4 | package main 5 | 6 | imprt ( 7 | "fmt" 8 | "time" 9 | "sync/atomic" 10 | "runtime" 11 | ) 12 | 13 | func main() { 14 | 15 | var ops uint64 = 0 16 | 17 | //为了模拟并发更新,启动了50个Go协程 18 | for i := 0; i < 50; i++ { 19 | go func() { 20 | for { 21 | 22 | //使用AddUint64来让计数器自动增加,使用&语法来 23 | //给出ops的内存地址 24 | atomic.AddUint64(&ops,1) 25 | 26 | //允许其它Go协程的执行 27 | runtime.Goshed() 28 | } 29 | }() 30 | } 31 | 32 | //等待一秒,让ops的并行自加操作执行一会儿 33 | time.Sleep(time.Second) 34 | 35 | //为了在计数器还在被其它Go协程更新时,安全的使用它,通过LoadUint64将 36 | //当前值拷贝提取到opsFinal中,需要给这个函数所取值的内存地址&ops。 37 | opsFinal := atomic.LoadUint64(&ops) 38 | fmt.Println("ops:",opsFinal) 39 | } 40 | 41 | ============================================================================== 42 | ============================================================================== 43 | -------------------------------------------------------------------------------- /Go语言技巧/r.go状态协程: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | 用互斥锁进行明确的锁定来让共享的值跨多个Go协程同步访问。另一个选择是使用内置的 3 | Go协程和通道的同步特性来达到同样的效果,就是将需要共享和同步的数据以结构体的行 4 | 式来定义成Go通道,以确保结构体形式的每块数据有单独的Go协程来操作。 5 | 基于Go协程的比基于互斥锁的稍复杂,但这在某些场合有用,例如,在有其他通道包含其 6 | 中或者当管理多个互斥锁的场合。 7 | ------------------------------------------ 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "math/rand" 13 | "sync/atomic" 14 | "time" 15 | ) 16 | 17 | //结构体数据类型,用于定义同步通道的数据类型,其中字段包括channel类型 18 | type readOp struct { 19 | key int 20 | resp chan int 21 | } 22 | 23 | //结构体数据类型,用于定义同步通道的数据类型,其中字段包括channel类型 24 | type writeOp struct { 25 | key int 26 | val int 27 | resp chan bool 28 | } 29 | 30 | func main() { 31 | 32 | //定义计算执行操作的次数 33 | var ops int64 34 | 35 | //定义结构体数据类型的同步通道 36 | reads := make(chan *readOp) 37 | writes := make(chan *writeOp) 38 | 39 | //拥有state的Go协程,这个协程反复响应到达的请求,然后返回一个值到响应 40 | //通道resp来表示操作成功。 41 | go func() { 42 | var state = make(map[int]int) 43 | for { 44 | select { 45 | case read :=<-reads: 46 | read.resp <- state[read.key] 47 | case write :=<-writes: 48 | state[write.key] = write.val 49 | write.resp <- true 50 | } 51 | } 52 | }() 53 | 54 | //启动100个Go协程模拟读操作 55 | for r := 0; r < 100; r++ { 56 | go func() { 57 | for { 58 | read := &readOp { 59 | key:rand.Intn(5), 60 | resp:make(chan int)} 61 | reads <- read 62 | <-read.resp 63 | atomic.AddInt64(&ops,1) 64 | } 65 | }() 66 | } 67 | 68 | //启动10个Go协程模拟协操作 69 | for w := 0; w < 10; w++ { 70 | go func() { 71 | for { 72 | write := &writeOp { 73 | key:rand.Intn(5), 74 | val:rand.Intn(100), 75 | resp:make(chan bool)} 76 | writes <-write 77 | <-write.resp 78 | atomic.AddInt64(&ops,1) 79 | } 80 | }() 81 | } 82 | 83 | //让这些Go协程运行1s 84 | time.Sleep(time.Second) 85 | 86 | opsFinal := atomic.LoadInt64(&ops) 87 | fmt.Println("ops:",opsFinal) 88 | } 89 | //这个例子中,模拟读写的Go协程将发送一条数据到拥有state的Go协程中,然后接受对 90 | //应的回复。结构体readOp和writeOp封装这些请求,并且是拥有Go协程响应的一个方式 91 | ============================================================================== 92 | ============================================================================== 93 | -------------------------------------------------------------------------------- /Go语言技巧/s.go-URL解析: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | URL提供了一个统一资源定位方式。 3 | net/url.Parse() 解析URL 4 | net/url.Scheme scheme 5 | net/url.User 包含了所有的认证信息 6 | net/url.User.Username() 认证信息的用户名 7 | net/url.User.Password() 认证信息的密码 8 | net/url.Host 包含主机名和端口信息 9 | net/url.Path 包含路径信息 10 | net/url.Fragment 包含查询片段信息 11 | net/url.RawQuery 得到字符串中k=v这种格式的查询参数 12 | --------------------------------------------------- 13 | package main 14 | 15 | import ( 16 | "fmt" 17 | "net/url" 18 | "strings" 19 | ) 20 | 21 | func main() { 22 | s := "postgres://user:pass@host.com:5432/path?k=v#f" 23 | 24 | u,err := url.Parse(s) 25 | if err != nil { 26 | panic(err) 27 | } 28 | 29 | fmt.Println(u.Scheme) 30 | 31 | fmt.Println(u.User) 32 | fmt.Println(u.User.Username()) 33 | p,_ := u.User.Password() 34 | fmt.Println(p) 35 | 36 | fmt.Println(u.Host) 37 | h := strings.Split(u.Host,":") 38 | fmt.Println(h[0]) 39 | fmt.Println(h[1]) 40 | 41 | fmt.Println(u.Path) 42 | fmt.Println(u.Fragment) 43 | 44 | fmt.Println(u.RawQuery) 45 | m,_ := url.ParseQuery(u.RawQuery) 46 | fmt.Println(m) 47 | fmt.Println(m["k"][0]) 48 | } 49 | 50 | ============================================================================== 51 | ============================================================================== 52 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | #说明: 2 | 这个项目总的来说是介绍Go语言和学习Go语言的,并且是基于linux环境。 3 | ##[0document](https://github.com/yaouser/Go-basic-code/tree/master/0document) 4 | 此目录是一些介绍git和sublime工具的使用方法。git是个软件版本控制工具,主要 5 | 是一些在linux下的一些实用命令,这样可以让你托管一些自已有趣的Go项目代码。 6 | sublime是一个比较流行的代码编辑器,主要是一些高效编程的快捷键的说明,它可以 7 | 帮助你快速的阅读和编写Go代码。还有一些关于linux和shell的一些有趣的文档和shell 8 | 脚本程序,能够让你更好的理解linux命令行环境。 9 | ##[Go Tool Command](https://github.com/yaouser/GoUnix/blob/master/0document/Go-command/SUMMARY.md) 10 | Go语言的命令行工具介绍,这个目录是fork于郝林的一个项目,由来请看[这里](https://github.com/hyper-carrot/go_command_tutorial). 11 | 尤其是pprof工具写的不错.注意请先查看这部分内容的[协议](https://github.com/yaouser/GoUnix/blob/master/0document/Go-command/LICENSE). 12 | ##[Go语言技巧](https://github.com/yaouser/Go-basic-code/tree/master/2Go技巧) 13 | 此目录介绍一些Go语言的小技巧,这些技巧会让你更好的理解Go语言。 14 | ##其它目录就是依次由浅入深的介绍Go语言特性。 15 | ##[SHELL应用](https://github.com/yaouser/Go-basic-code/tree/master/0document/SHELL-BASE) 16 | 在linux的环境下,也许需要深入的了解一下系统的解释环境(shell),这样我们才知道 17 | 工作在什么样的环境。如果你想知道更加底层是怎么工作的,请找[kernel](https://www.kernel.org/)。它会告诉你的。 18 | ##[X-Project](https://github.com/yaouser/GoUnix/tree/master/x-project) 19 | 关于Go语言一些重量级应用的介绍和使用,如Docker Etcd Kubernetes ..... 20 | ##Email:yaozhenqian2015@gmail.com(这个Email被Google封掉了!) 21 | -------------------------------------------------------------------------------- /x-project/docker/e.mysql-dockerfile: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | 3 | ##Dockerfile## 4 | 5 | FROM centos 6 | MAINTAINER Yaouser 7 | 8 | WORKDIR /root/ 9 | 10 | RUN yum -y update; yum clean all 11 | RUN yum -y install wget; yum clean all 12 | RUN wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm 13 | RUN rpm -ivh /root/mysql-community-release-el7-5.noarch.rpm 14 | #必须要导入新仓库的密玥,否则安装mysql无法正常进行. 15 | RUN rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-mysql 16 | 17 | RUN yum -y install mysql-community-server; yum clean all 18 | RUN mysql_install_db --user=mysql 19 | ENV MYSQL_USER test 20 | ENV MYSQL_PASS mypassword 21 | #让容器支持中文,centos容器默认是不支持中文的. 22 | ENV LC_ALL en_US.UTF-8 23 | ADD build_table.sh /root/build_table.sh 24 | RUN chmod u+x /root/build_table.sh 25 | RUN /root/build_table.sh 26 | EXPOSE 3306 27 | ADD run.sh /root/run.sh 28 | RUN chmod u+x /root/run.sh 29 | CMD [/root/run.sh] 30 | 31 | ##Dockerfile## 32 | 33 | yum clean all是为了删除掉下载的缓存文件,防止制作的镜像过大. 34 | 35 | 解决mysql安装时,提示没有安装KEY(安装官方仓库软件不会有这样的情况) 36 | 1 rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-mysql 37 | 2 yum install mysql-community-server --nogpgcheck 38 | 39 | ------------------------------------------------------ 40 | 41 | 运行mysql数据库 42 | 43 | ##run.sh## 44 | 45 | #!/bin/bash 46 | mysqld_safe 47 | 48 | ------------------------------- 49 | 50 | 创建数据库表 51 | 52 | ##build_table.sh## 53 | 54 | #!/bin/bash 55 | mysqld_safe & 56 | sleep 3 57 | mysql -e "GRANT ALL PRIVILEGES ON *.* TO '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASS' WITH GRANT OPTION;" 58 | mysql -e "create database scores" 59 | mysql -e "create table scores.name_score(name char(20) not null,score int not null) DEFAULT CHARSET=utf8" 60 | mysql -e "insert into scores.name_score values ('李明',80),('张军',90),('王小二',95)" 61 | 62 | ##build_table.sh## 63 | 64 | 注意: 65 | 在建立一个大表时,可以将建表语句抽象出来形成一个文件create.sql,之后可以执行语句 66 | mysql -e "source create.sql". 67 | 68 | ============================================================================== 69 | ============================================================================== 70 | -------------------------------------------------------------------------------- /x-project/etcd/etcd-proxy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaouser/GoUnix/139f9e7778938c22e222743427952ee9056585d9/x-project/etcd/etcd-proxy.jpg -------------------------------------------------------------------------------- /x-project/etcd/etcd-scenes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaouser/GoUnix/139f9e7778938c22e222743427952ee9056585d9/x-project/etcd/etcd-scenes.pdf -------------------------------------------------------------------------------- /x-project/etcd/raft.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaouser/GoUnix/139f9e7778938c22e222743427952ee9056585d9/x-project/etcd/raft.pdf -------------------------------------------------------------------------------- /x-project/kubernetes/Borg.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaouser/GoUnix/139f9e7778938c22e222743427952ee9056585d9/x-project/kubernetes/Borg.pdf -------------------------------------------------------------------------------- /x-project/kubernetes/kubernetes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaouser/GoUnix/139f9e7778938c22e222743427952ee9056585d9/x-project/kubernetes/kubernetes.jpg -------------------------------------------------------------------------------- /x-project/kubernetes/label.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yaouser/GoUnix/139f9e7778938c22e222743427952ee9056585d9/x-project/kubernetes/label.jpg --------------------------------------------------------------------------------