go语言编程笔记--入门篇
Hello world
//hello.go
package main
import "fmt"
func main(){
str := "hello 世界"
for _, v := range str {
fmt.Printf("%c ", v)
}
}
此处入门代码不只是简单的fmt.Println("Hello world!")
,有以下几点需要注意:
- main函数包名
package main
- 导入包
import "fmt"
,注意引号 - go天然支持unicode, 打印非英文的hello world, Printf中的
%...
称为verb, %c表示打印字符(rune, Unicode码点) - 用range for自动识别有效value, 如果打印index,会发现一共8次循环(0~5,6,9), 因为汉字占3个字节
- 用这种方式可以打印世界各种语言unicode编码字符集
echo命令行
package main
import (
"os"
"fmt"
"strings"
)
func main() {
var sep, s string
for _, v := range os.Args[1:] {
s += sep + v
sep = " "
}
fmt.Println(s)
// 直接打印,使用strings包的Join
fmt.Println(strings.Join(os.Args[1:], " "))
}
- 第一个for循环中
s+= sep + v
有一个技巧, 最初的seq为零值, 统一处理,避免多一个空格的问题 -
os
包的命令行参数 -
strings
包处理字符串,Join
把slice中元素连接成一个字符串
查找重复行
package reader
import (
"bufio"
"fmt"
"os"
)
func main() {
input := bufio.NewScanner(os.Stdin)
counter := make(map[string]int, 0)
for input.Scan() {
if input.Text()=="q" {
break
}
counter[input.Text()]++
}
for k, v := range counter {
if v > 1 {
fmt.Println(k)
}
}
}
统计有重复的行并打印,主要借助map统计
- map使用make创建的一个引用, 键只要可以施加==比较即可
- map的每次迭代顺序随机,因为程序无法保证map迭代的顺序
- bufio包处理输入和输出方便又高效.Scanner读取输入并将其拆成行或单词
- 从文件读取可以
os.Open(filename)
-->*os.File, 或这用ioutil.ReadFile(filename)
-->返回一个字节切片(byte slice读取全文 - 常见转义格式字符
verb | comments |
---|---|
%d | 十进制整数 |
%x, %o, %b | 十六进制, 八进制, s二进制整数 |
%f, %g, %e | 浮点数: 3.141593 3.141592653589793 3.141593e+00 |
%t | 布尔:true或false |
%c | 字符(rune) (Unicode码点) |
%s | 字符串 |
%q | 带双引号的字符串"abc"或带单引号的字符'c' |
%v | 变量的自然形式(natural format) |
%T | 变量的类型 |
%% | 字面上的百分号标志(无操作数) |
flag包, 解析命令行
package main
import "flag"
func main(){
strFlag := flag.String("key", "default_value", "comments of the flag")
flag.Parse()
print(*strFlag)
}
- flag.String()/Int/Bool等返回的是指针,对应变量版本flag.StringVar(&varname,xxx)
- docker使用的cli是非常棒的第三方包
获取url
package networker
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
)
func main() {
for _, url := range os.Args[1:] {
url:=url
go func(){
resp, err := http.Get(url)
if err != nil {
os.Exit(1)
}
b, err := ioutil.ReadAll(resp.Body)
defer resp.Body.Close()
if err != nil {
os.Exit(1)
}
fmt.Println(string(b))
}()
}
}
- 使用goroutine并发发送Get请求(net/http)
- Body是一个io.ReadCloser对象,即实现了io.Reader跟io.Closer接口的对象
- ioutil.ReadAll读取resp中的Body全部内容
-
url:=url
声明局部变量, 以防多个goroutine产生数据竞争
web server
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"sync"
)
var mu sync.Mutex
var cnt int
func main() {
http.HandleFunc("/", handler)
http.HandleFunc("/count", counter)
//http.HandleFunc("/", handler) // each request calls handler
log.Fatal(http.ListenAndServe("localhost:8000", nil))
}
// handler echoes the Path component of the request URL r.
func handler(w http.ResponseWriter, r *http.Request) {
mu.Lock()
cnt++ // 访问次数统计
mu.Unlock()
fmt.Fprintf(w, "%s %s %s\n", r.Method, r.URL, r.Proto)
for k, v := range r.Header {
fmt.Fprintf(w, "Header[%q] = %q\n", k, v)
}
fmt.Fprintf(w, "Host = %q\n", r.Host)
fmt.Fprintf(w, "RemoteAddr = %q\n", r.RemoteAddr)
if err := r.ParseForm(); err != nil {
log.Print(err)
}
for k, v := range r.Form {
fmt.Fprintf(w, "Form[%q] = %q\n", k, v)
}
}
func counter(w http.ResponseWriter, r *http.Request) {
mu.Lock()
fmt.Fprintf(w, "Count %d\n", cnt)
mu.Unlock()
}
-
/
开头的请求为发送到当前站点上的所有请求,监听8000端口 - handler实现接口
func(ResponseWriter, *Request)
-
sync.Mutex
互斥量并发控制增加访问计数 - 此示例打印了许多request相关信息,后续有详解
switch 跟无tag switch
switch coinflip() {
case "heads":
heads++
case "tails":
tails++
default:
fmt.Println("landed on edge!")
}
func Signum(x int) int {
switch {
case x > 0:
return +1
default:
return 0
case x < 0:
return -1
}
}
网友评论