go-入门 - Go语言中文社区

go-入门


hello world

go原生支持Unicode,所以可以支持处理任何国家的语言,go是编译型语言,通过go的自命令run可以将go源码编译、链接、生成可执行文件并执行。

$ go run helloworld.go

一个简单的helloworld程序如下所示:

//要运行的包必须为main
package main

import "fmt"
func main() {
	fmt.Println("hello world")
}

go run 命令不会输出生成的中间可执行文件,如果要生成一个可以复用的可执行文件,可以使用go build命令,这会生成一个名为helloworld的可执行文件,然后可以运行该文件。

//编译
$ go build helloworld.go
//运行
$ ./helloworld

程序结构

go组织程序的方式类似于java,也是通过包来组织不同模块的代码。每一个go文件的开头需要声明所属于的包。
main这个包是很特殊的一个包名,它用来定义一个单独的可执行程序,而不是库。
go的基础库中有100多个包,用来完成文件操作,数学计算,网络处理等基础任务。例如fmt包,可以用来将输出格式化并写入标准输出。
通过import引入需要使用的包,但是***go对引入的包有严格的规范,只能引入要使用的包,如果引入没有使用的包,程序编译会失败***。这一点与java不同,java并不做严格的限制,可以引入不使用的包。
main函数类似其他语言的main函数的作用,就是程序的入口函数。

函数的声明包括:
func关键字 函数名 参数列表 返回值列表(可以为空) 放在大括号内的函数体

例子

命令行参数 os.Args

***os***包提供了一些函数和变量,以平台无关的方式与操作系统交互。
命令行参数通过os.Args变量来访问。
os.Args是一个字符串slice。
os.Args[0] 表示的是运行的程序本身

package main

import (
	"fmt"
	"os"
	"strings"
)

func main(){
	var s, temp string
	for i:= 0; i< len(os.Args) ; i++  {
		s += temp + os.Args[i]
		temp = " "
	}
	fmt.Println(s)

	s = ""
	temp = ""
	//or
	for _, arg := range os.Args[:] {
		s += temp + arg
		temp = " "
	}
	fmt.Println(s)

	//or
	fmt.Println(strings.Join(os.Args," "))
}

第二中方式的 “_” 表示空标志符,因为go不允许声明不使用的变量,但是range操作会产生一对值(这里是数组的索引和该索引上的值),所以必须拿一个空标志符来接收。

找出重复行

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main(){
	counts := make(map[string]int)
	input := bufio.NewScanner(os.Stdin)

	for input.Scan() {
		if "" == input.Text(){
			break
		}
		counts[input.Text()]++
	}

	for line, n := range counts{
		if n > 1{
			fmt.Printf("%dt%sn", n, line)
		}
	}
}

make语法可以用于创建一个固有格式的map(键可以是允许相等(==)比较的类型,例如上面的string,值可以是任意类型)。例如上面的声明表示key为string,value为int。
counts[input.Text()]++ 这个语句等价于:

templine := input.Text()
counts[templine] = counts[templine] + 1

bufio包可以用来高效的处理输入输出。其中一个很有用的特性就是扫描器(Scanner),它可以读取输入,以行或者单词为单位断开,这是处理以行为单位的输入内容的最简单方式。
scan()方法在读到新行时返回true,没有更多内容时返回false。使用text()方法获取读到的数据。

字符串格式化

go多线程

例子

package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"time"
)

func main() {
	startTime := time.Now()
	//创建string通道
	ch := make(chan string)
	//遍历参数传入的url
	for _, url := range os.Args[1:] {
		//启动一个goroutine
		go fetch(url, ch)
	}
	//从通道读数据
	for range os.Args[1:] {
		fmt.Println(<-ch)
	}
	//统计用时
	pass := time.Since(startTime).Seconds()
	fmt.Println("总用时%.2f秒", pass)
}

func fetch(url string, ch chan<- string) {
	startTime := time.Now()
	resp, err := http.Get(url)
	if err != nil {
		//写入到通道
		ch <- fmt.Sprint(err)
		return
	}
	//拷贝到目的地 返回拷贝的字节数 第一个参数是目的地 这里是一个“丢弃”目的地
	nbytes, err := io.Copy(ioutil.Discard, resp.Body)
	//关闭资源
	resp.Body.Close()
	if nil != err {
		//写入通道
		ch <- fmt.Sprintf("while reading %s: err:%v", url, err)
		return
	}
	//统计用时
	pass := time.Since(startTime).Seconds()
	//写入通道
	ch <- fmt.Sprintf("用时%.2f秒 数据量%7d字节 url:%s", pass, nbytes, url)
}

注意:通道是阻塞式的发送与接受数据方式,当一个goroutine试图在一个通道上进行发送或接收操作时,它会阻塞,直到另一个goroutine试图进行接收或发送操作才传递值

http服务器

示例

package main

import (
	"fmt"
	"log"
	"net/http"
	"sync"
)

var mu sync.Mutex
var count int

func main()  {
	http.HandleFunc("/", handler)
	http.HandleFunc("/count", counter)
	log.Fatal(http.ListenAndServe("localhost:8000",nil))

}

func counter(w http.ResponseWriter, r *http.Request) {
	mu.Lock()
	fmt.Fprintf(w, "count %dn", count)
	mu.Unlock()
}

func handler(w http.ResponseWriter, r *http.Request)  {
	//输出http方法,URL,协议
	fmt.Fprintf(w, "%s %s %s n", r.Method, r.URL, r.Proto)
	//输出Header
	for k,v := range r.Header {
		fmt.Fprintf(w, "Header[%q] = %q n", k, v)
	}
	//输出host
	fmt.Fprintf(w, "HOST = %qn", r.Host)
	//输出RemoteAddr
	fmt.Fprintf(w, "RemoteAddr = %q n", r.RemoteAddr)

	//if 内部定义局部变量
	if err := r.ParseForm(); err != nil {
		log.Println(err)
	}

	//输出Form内数据
	for k,v := range r.Form {
		fmt.Fprintf(w, "Form[%q] = %qn", k, v)
	}

	//通过sysc.Mutex实现请求计数
	mu.Lock()
	count++
	mu.Unlock()

	fmt.Fprintf(w, "URL.PATH = %qn", r.URL.Path)
}


版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/zhruixuan/article/details/89639952
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢