版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mhw828/article/details/80703706
GOLang 笔记
2018/1/1 12:12:17
环境搭建
Go软件下载地址
安装
推荐IDE GoLand
安装
IDE 注册服务器
http://btsha.com:41017
IDE 配置
API 地址
https://studygolang.com/pkgdoc
环境变量介绍
GOPATH
工程目录
GOROOT
Go软件的安装目录
经典程序 Hello World
// 必须为main
package main
import "fmt"
//程序入口
func main() {
//打印输出
fmt.Println("Hello World")
}
25关键字
break | default | func | interface | select |
case | defer | go | map | struct |
chan | else | goto | package | switch |
const | fallthrough | if | range | type |
continue | for | import | return | var |
36 个预定义标识符
append | bool | byte | cap | close | complex | complex64 | complex128 | uint16 |
copy | false | float32 | float64 | imag | int | int8 | int16 | uint32 |
int32 | int64 | iota | len | make | new | nil | panic | uint64 |
println | real | recover | string | true | uint | uint8 | uintptr |
变量
package main
import "fmt"
// 变量 字符串
var name = "ms~go"
// 整数
var age = 23
//字符串
var address = "beijing"
// 布尔类型
var sex = true
//常量
const year = 2018
//字符
var c = 'c'
func main() {
fmt.Println(name)
fmt.Println(age)
fmt.Println(sex)
fmt.Println(year)
var a = 1.5
var b = 2.5
//计算加法
fmt.Println(a + b)
}
var (
a int = 10
b float64 = 100
)
a, b := 20, 30
_, b := 34, 35
丢弃34
“_” 代表丢弃的意思
数学运算
package main
import "fmt"
func main() {
var a = 0xff
var b = 10
fmt.Println(a + b)
fmt.Println(a - b)
fmt.Println(a * b)
fmt.Println(a / b)
fmt.Println(a % b)
fmt.Println(a > b)
fmt.Println(a < b)
fmt.Println(a <= b)
fmt.Println(a >= b)
fmt.Println(a >> 1)
fmt.Println(b << 1)
fmt.Println(b | 1)
fmt.Println(b & 1)
fmt.Println(b != 1)
}
随机数
package main
import (
"fmt"
"time"
"math/rand"
)
func main() {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i:=0; i<10; i++ {
fmt.Println(r.Intn(100))
}
}
数组
package main
import (
"fmt"
"time"
"math/rand"
)
func main() {
// 常量数组长度
const N = 10
//声明数组
var arr = [N]int{}
//随机数
r := rand.New(rand.NewSource(time.Now().UnixNano()))
//循环赋值
for i := 0; i < len(arr); i++ {
//赋值
arr[i] = r.Intn(0xff)
}
//打印数组
fmt.Println(arr)
/*******************************************
冒泡排序
********************************************/
//:=自动匹配变量类型
num := len(arr)
//花括号{必须在这一行 if也一样
for i := 0; i < num; i++ {
for j := i + 1; j < num; j++ {
if arr[i] > arr[j] {
//相比某语言不需要临时交换变量
arr[i], arr[j] = arr[j], arr[i]
}
}
}
//输出排序后的数组
fmt.Println(arr)
}
指针
package main
import "fmt"
func main() {
// 声明变量
var a int = 10
var b int = 10
//打印地址
fmt.Println("pointer address : %x", &a)
fmt.Println("pointer address : %x", &b)
//判断地址是否相同
fmt.Println(&a == &b)
//值赋值
var c = a
//值赋值
var d = b
//打印值
fmt.Println(c)
//打印地址
fmt.Println("pointer address : %x", &c)
//打印值
fmt.Println(d)
//打印地址
fmt.Println("pointer address : %x", &d)
//取地址
var e = &a
//取地址
var f = &a
//输出地址
fmt.Println("pointer address : %x", &e)
//输出地址
fmt.Println("pointer address : %x", &f)
//输出值
fmt.Println(e)
//输出值
fmt.Println(f)
//判断地址是否相同
fmt.Println(e == f)
//指针类型
var ip *int = &a
//打印指针
fmt.Println(ip)
//二级指针
var jp **int = &ip
fmt.Println(jp)
//三级指针
var kp ***int = &jp;
fmt.Println(kp)
arr := []int{10, 100, 200}
var i int
for i = 0; i < len(arr); i++ {
fmt.Printf("a[%d] = %d | %x \n", i, arr[i], &arr[i])
}
}
MD5
package main
import (
"crypto/md5"
"fmt"
"encoding/hex"
)
func main() {
md5Ctx := md5.New()
md5Ctx.Write([]byte("ms~go"))
cipherStr := md5Ctx.Sum(nil)
fmt.Println(cipherStr)
fmt.Println(hex.EncodeToString(cipherStr))
}
sha 256
package main
import (
"crypto/sha256"
"fmt"
)
func main() {
h := sha256.New()
h.Write([]byte("ms~go"))
fmt.Printf("%x", h.Sum(nil))
}
iota
package main
import "fmt"
func main() {
//为 0
const a = iota
const (
//没增加一行+1
b = iota
c = iota
d = iota
e, f = iota, iota
// 同一行数值相等
g, h, i, j, k = iota, iota, iota, iota, iota
)
fmt.Printf("a = %d , b = %d , c = %d , d = %d , e = %d , f = %d , g = %d , h = %d , i = %d , j = %d , k = %d ", a, b, c, d, e, f, g, h, i, j, k)
//每次 const 出现时,都会让 iota 初始化为0.
const l = iota
fmt.Println(l)
}
// 自增长类型
const (
a = iota
b
c
d
)
使用 “_” 可以跳过值
const (
a = iota
b
c
// 使用 "_" 可以跳过值
_
_
d
)
位掩码表达式
const(
a=1<<iota
b
c
d
e
f
_
g
h
)
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
fmt.Println(d)
fmt.Println(e)
fmt.Println(f)
fmt.Println(g)
fmt.Println(h)
GOROOT=D:\Go #gosetup
GOPATH=E:\GoProject;D:\Go #gosetup
D:\Go\bin\go.exe build -i -o C:\Users\maohuawei\AppData\Local\Temp\___go_build_main_go.exe E:/GoProject/src/ExampleCode/main/main.go #gosetup
"C:\Program Files\JetBrains\GoLand 2018.1.4\bin\runnerw.exe" C:\Users\maohuawei\AppData\Local\Temp\___go_build_main_go.exe #gosetup
1
2
4
8
16
32
128
256
定义数量级
type ByteSize float64
const (
_ = iota // ignore first value by assigning to blank identifier
KB ByteSize = 1 << (10 * iota) // 1 << (10*1)
MB // 1 << (10*2)
GB // 1 << (10*3)
TB // 1 << (10*4)
PB // 1 << (10*5)
EB // 1 << (10*6)
ZB // 1 << (10*7)
YB // 1 << (10*8)
)
文件
package main
import (
"bufio" //缓存IO
"fmt"
"io"
"io/ioutil" //io 工具包
"os"
)
func check(e error) {
if e != nil {
panic(e)
}
}
/**
* 判断文件是否存在 存在返回 true 不存在返回false
*/
func checkFileIsExist(filename string) bool {
var exist = true
if _, err := os.Stat(filename); os.IsNotExist(err) {
exist = false
}
return exist
}
/**
from: http://www.isharey.com/?p=143
*/
func main() {
var wireteString = "测试n"
var filename = "./output1.txt"
var f *os.File
var err1 error
/***************************** 第一种方式: 使用 io.WriteString 写入文件 ***********************************************/
if checkFileIsExist(filename) { //如果文件存在
f, err1 = os.OpenFile(filename, os.O_APPEND, 0666) //打开文件
fmt.Println("文件存在")
} else {
f, err1 = os.Create(filename) //创建文件
fmt.Println("文件不存在")
}
check(err1)
n, err1 := io.WriteString(f, wireteString) //写入文件(字符串)
check(err1)
fmt.Printf("写入 %d 个字节n", n)
/***************************** 第二种方式: 使用 ioutil.WriteFile 写入文件 ***********************************************/
var d1 = []byte(wireteString)
err2 := ioutil.WriteFile("./output2.txt", d1, 0666) //写入文件(字节数组)
check(err2)
/***************************** 第三种方式: 使用 File(Write,WriteString) 写入文件 ***********************************************/
f, err3 := os.Create("./output3.txt") //创建文件
check(err3)
defer f.Close()
n2, err3 := f.Write(d1) //写入文件(字节数组)
check(err3)
fmt.Printf("写入 %d 个字节n", n2)
n3, err3 := f.WriteString("writesn") //写入文件(字节数组)
fmt.Printf("写入 %d 个字节n", n3)
f.Sync()
/***************************** 第四种方式: 使用 bufio.NewWriter 写入文件 ***********************************************/
w := bufio.NewWriter(f) //创建新的 Writer 对象
n4, err3 := w.WriteString("bufferedn")
fmt.Printf("写入 %d 个字节n", n4)
w.Flush()
f.Close()
}
字典
package main
import "fmt"
func main() {
m:=make(map[string]string)
m["a"]="a"
m["b"]="b"
m["c"]="c"
// 打印字典
fmt.Println(m)
//字典长度
fmt.Println(len(m))
//根据键取值
fmt.Println(m["c"])
//删除
delete(m,"b")
fmt.Println(m)
}
字符串
package main
import (
"fmt"
"strings"
)
func main() {
var print = fmt.Println
print(strings.Contains("MS~GO","MS"))
print(strings.Join([]string{"a", "b", "c"}, "~"))
print(strings.Count("ms~go go go","go"))
print(strings.EqualFold("s","s"))
print(strings.Fields("abc"))
//比较
print(strings.Compare("aaa","aaa"))
}
自定义排序
package main
import "sort"
import "fmt"
// 为了能够使用自定义函数来排序,我们需要一个
// 对应的排序类型,比如这里我们为内置的字符串
// 数组定义了一个别名ByLength
type ByLength []string
// 我们实现了sort接口的Len,Less和Swap方法
// 这样我们就可以使用sort包的通用方法Sort
// Len和Swap方法的实现在不同的类型之间大致
// 都是相同的,只有Less方法包含了自定义的排序
// 逻辑,这里我们希望以字符串长度升序排序
func (s ByLength) Len() int {
return len(s)
}
func (s ByLength) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s ByLength) Less(i, j int) bool {
return len(s[i]) < len(s[j])
}
// 一切就绪之后,我们就可以把需要进行自定义排序
// 的字符串类型fruits转换为ByLength类型,然后使用
// sort包的Sort方法来排序
func main() {
fruits := []string{"a", "bb", "ccc","dddd","ee","121212"}
sort.Sort(ByLength(fruits))
fmt.Println(fruits)
}
Base64
package main
import base64 "encoding/base64"
import "fmt"
func main() {
data := "ms~go"
sEnc := base64.StdEncoding.EncodeToString([]byte(data))
fmt.Println(sEnc)
sDec, _ := base64.StdEncoding.DecodeString(sEnc)
fmt.Println(string(sDec))
fmt.Println()
uEnc := base64.URLEncoding.EncodeToString([]byte(data))
fmt.Println(uEnc)
uDec, _ := base64.URLEncoding.DecodeString(uEnc)
fmt.Println(string(uDec))
}
for 循环
package main
import (
"math/rand"
"fmt"
)
func main() {
var i=0
for i<100 {
fmt.Println(rand.Intn(0xff))
i++
}
}
package main
import (
"fmt"
)
func main() {
for i := 0; i <= 9; i++ {
fmt.Println(i)
}
}
循环一次
package main
import (
"fmt"
)
func main() {
for {
fmt.Println("for")
break
}
}
if
package main
import (
"math/rand"
"fmt"
)
func main() {
var i=0
for i<100 {
fmt.Println(rand.Intn(0xff))
i++
if(i==2){
continue
}
if(i==10){
break
}
}
}
defer
Defer 用来保证一个函数调用会在程序执行的最后被调用。通常用于资源清理工作。
package main
import "fmt"
import "os"
func main() {
f := createFile("defer.txt")
defer closeFile(f)
writeFile(f)
}
func createFile(p string) *os.File {
f, err := os.Create(p)
if err != nil {
panic(err)
}
return f
}
func writeFile(f *os.File) {
fmt.Fprintln(f, "hello world defer")
}
func closeFile(f *os.File) {
if f != nil {
f.Close()
}
}
Exit
package main
import (
"os"
"fmt"
)
func main() {
var i = 0
for i < 100 {
fmt.Println(i)
if i == 50 {
os.Exit(0)
}
i++
}
}
if else
可变参数
package main
import "fmt"
func main() {
sop(123165,564,235235,5234234,54234,51,61,)
}
/**
可变参数
*/
func sop(args ...int) {
for i := 0; i < len(args); i++ {
fmt.Println(args[i])
}
}
函数作为返回值
package main
import "fmt"
func main() {
hello := func() {
println("hello")
}
hello()
//打印类型
fmt.Printf("%T", hello)
}
panic
package main
import "os"
func main() {
// 我们使用panic来检查预期不到的错误
panic("a problem")
// Panic的通常使用方法就是如果一个函数
// 返回一个我们不知道怎么处理的错误的
// 时候,直接终止执行。
_, err := os.Create("1.txt")
if err != nil {
panic(err)
}
}
键盘输入
package main
import (
"bufio"
"os"
"fmt"
"strings"
)
func main() {
// 键盘输入
scanner := bufio.NewScanner(os.Stdin)
//循环获取输入
for scanner.Scan() {
//打印 转换为大写
fmt.Println(scanner.Text() + " || " + strings.ToUpper(scanner.Text()))
}
//检查错误。文件结束不会被当作一个错误
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "error:", err)
os.Exit(0)
}
}
range
package main
import "fmt"
func main() {
sop(1, 2, 4, 6, 8, 10)
}
func sop(args ...int) {
for _, i := range args {
fmt.Println(i)
}
}
for i, c := range "AB" {
fmt.Println(i, c)
}
SH1
package main
import (
"crypto/sha1"
"fmt"
)
func main() {
s1 := sha1.New()
s1.Write([]byte("ms~go"))
bs := s1.Sum(nil)
fmt.Printf("%x", bs)
}
结构体
package main
import "fmt"
// 这个person结构体有name和age成员
type person struct {
name string
age int
}
func main() {
// 这个语法创建一个新结构体变量
fmt.Println(person{"Bob", 20})
// 可以使用"成员:值"的方式来初始化结构体变量
fmt.Println(person{name: "Alice", age: 30})
// 未显式赋值的成员初始值为零值
fmt.Println(person{name: "Fred"})
// 可以使用&来获取结构体变量的地址
fmt.Println(&person{name: "Ann", age: 40})
// 使用点号(.)来访问结构体成员
s := person{name: "Sean", age: 50}
fmt.Println(s.name)
// 结构体指针也可以使用点号(.)来访问结构体成员
// Go语言会自动识别出来
sp := &s
fmt.Println(sp.age)
// 结构体成员变量的值是可以改变的
sp.age = 51
fmt.Println(sp.age)
}
URL解析
package main
import "fmt"
import "net/url"
import "strings"
func main() {
// 我们将解析这个URL,它包含了模式,验证信息,
// 主机,端口,路径,查询参数和查询片段
s := "postgres://user:pass@host.com:5432/path?k=v#f"
// 解析URL,并保证没有错误
u, err := url.Parse(s)
if err != nil {
panic(err)
}
// 可以直接访问解析后的模式
fmt.Println(u.Scheme)
// User包含了所有的验证信息,使用
// Username和Password来获取单独的信息
fmt.Println(u.User)
fmt.Println(u.User.Username())
p, _ := u.User.Password()
fmt.Println(p)
// Host包含了主机名和端口,如果需要可以
// 手动分解主机名和端口
fmt.Println(u.Host)
h := strings.Split(u.Host, ":")
fmt.Println(h[0])
fmt.Println(h[1])
// 这里我们解析出路径和`#`后面的片段
fmt.Println(u.Path)
fmt.Println(u.Fragment)
// 为了得到`k=v`格式的查询参数,使用RawQuery。你可以将
// 查询参数解析到一个map里面。这个map为字符串作为key,
// 字符串切片作为value。
fmt.Println(u.RawQuery)
m, _ := url.ParseQuery(u.RawQuery)
fmt.Println(m)
fmt.Println(m["k"][0])
}
内存分配
package main
import (
"sync"
"bytes"
"fmt"
)
type SyncedBuffer struct {
lock sync.Mutex
bbuffer bytes.Buffer
}
func main() {
_ = new(SyncedBuffer)
var _ SyncedBuffer
var p1 *[]int = new([]int)
var p2 []int = make([]int,10000)
fmt.Printf("%p", p1)
fmt.Printf("%p", p2)
}
自定义类型
package main
import "fmt"
// 自定义类型
type ms string
//结构体
type person struct {
name ms
}
func main() {
var p1 = new(person)
p1.name="ms"
fmt.Println(p1)
}
类型转换
package main
import "fmt"
func main(){
var a int = 10
fmt.Println(a)
var b float64=float64(a)
fmt.Println(b)
}
接口
package main
import "fmt"
import "math"
// 这里定义了一个最基本的表示几何形状的方法的接口
type geometry interface {
area() float64
perim() float64
}
// 这里我们要让正方形square和圆形circle实现这个接口
type square struct {
width, height float64
}
type circle struct {
radius float64
}
// 在Go中实现一个接口,只要实现该接口定义的所有方法即可
// 下面是正方形实现的接口
func (s square) area() float64 {
return s.width * s.height
}
func (s square) perim() float64 {
return 2*s.width + 2*s.height
}
// 圆形实现的接口
func (c circle) area() float64 {
return math.Pi * c.radius * c.radius
}
func (c circle) perim() float64 {
return 2 * math.Pi * c.radius
}
// 如果一个函数的参数是接口类型,那么我们可以使用命名接口
// 来调用这个函数
// 比如这里的正方形square和圆形circle都实现了接口geometry,
// 那么它们都可以作为这个参数为geometry类型的函数的参数。
// 在measure函数内部,Go知道调用哪个结构体实现的接口方法。
func measure(g geometry) {
fmt.Println(g)
fmt.Println(g.area())
fmt.Println(g.perim())
}
func main() {
s := square{width: 3, height: 4}
c := circle{radius: 5}
// 这里circle和square都实现了geometry接口,所以
// circle类型变量和square类型变量都可以作为measure
// 函数的参数
measure(s)
measure(c)
}
数组和冒泡
package main
import "fmt"
func main() {
arr := []int{10, 12, 33, 14, 65}
for _, i := range arr {
fmt.Printf("%d ",i)
}
fmt.Println()
bubblesort(arr)
for _, i := range arr {
fmt.Printf("%d ",i)
}
}
func bubblesort(n[]int) {
for i := 0; i < len(n)-1; i++ {
for j := i + 1; j < len(n); j++ {
if n[j] < n[i] {
n[i], n[j] = n[j], n[i]
}
}
}
}
一维数组,二位数组,二维数组的转置
package main
import "fmt"
func main() {
var a [5]int
a[0] = 1024 >> 10
fmt.Printf("%d \n", a)
var c = 0
var b [3][3]int
var d [3][3]int
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
c++
b[i][j] = c
}
}
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Printf("%d ", b[i][j])
}
fmt.Println()
}
fmt.Println("----------")
for i := 0; i < len(b); i++ {
for j := 0; j < len(b[0]); j++ {
d[i][j] = b[j][i]
}
}
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
fmt.Printf("%d ", d[i][j])
}
fmt.Println()
}
}
超时时间
package main
import "time"
func main() {
c := make(chan int)
o := make(chan bool)
go func() {
for {
select {
case v := <-c:
println(v)
case <-time.After(5 * time.Second):
println("timeout")
o <- true
break
}
}
}()
<-o
}
json 编码与解析
package main
import "encoding/json"
import "fmt"
type Person struct {
Name string
Age int
Sex bool
}
func main() {
/*****json转换*****/
//创建对象
person := Person{
"ms~go",
23,
true,
}
//json编码
personjson, _ := json.Marshal(person)
//输出json字符串
fmt.Println(string(personjson))
/*****json解析*****/
strjson := `{"Name":"ms~go","Age":23,"Sex":true}`
r := &Person{}
json.Unmarshal([]byte(strjson), &r)
fmt.Println(r)
fmt.Println(r.Name)
fmt.Println(r.Age)
fmt.Println(r.Sex)
}
查看某个环境变量
package main
import (
"os"
"fmt"
)
func main() {
ANDROID_HOME,AB:=os.LookupEnv("ANDROID_HOME")
fmt.Println(ANDROID_HOME)
fmt.Println(AB)
JAVA_HOME,JB:=os.LookupEnv("JAVA_HOME")
fmt.Println(JAVA_HOME)
fmt.Println(JB)
PATH,PB:=os.LookupEnv("PATH")
fmt.Println(PATH)
fmt.Println(PB)
}
执行CMD命令
package main
import "os/exec"
func main() {
cmdcalc := exec.Command("calc")
cmdcalc.Start()
cmdnotepad := exec.Command("notepad")
cmdnotepad.Start()
cmdmspaitn := exec.Command("mspaint")
cmdmspaitn.Start()
}
http get 请求
package main
import (
"net/http"
"fmt"
"io/ioutil"
"os"
)
func main() {
//http 请求
resp, _ := http.Get("http://www.baidu.com/")
//defer 打开
defer resp.Body.Close()
//获取请求体
body, _ := ioutil.ReadAll(resp.Body)
//打印请求到的数据
fmt.Println(string(body))
//创建文件
os.Create("baidu.html")
//写入数据
ioutil.WriteFile("baidu.html", body, 777)
}
goroutine
package main
import (
"fmt"
"time"
)
func main() {
//必须先运行ms和ms1
//如果先运行for{} 则执行不到 ms() ms1()
go ms()
go ms1()
for {
fmt.Println("this is main ")
time.Sleep(time.Second)
}
}
// 函数1
func ms() {
for {
fmt.Println("this is ms")
time.Sleep(time.Second)
}
}
//函数2
func ms1() {
for {
fmt.Println("this is ms1")
time.Sleep(time.Second)
}
}
文件创建
package main
import (
"os"
"bufio"
)
func main() {
// 创建文件
f, _ := os.Create("hello world.txt")
//defer关闭文件
defer f.Close()
//写入文件 方法1
f.Write([]byte("hello world "))
//写入文件 方法2
f.WriteString("你是我的眼")
//同步文件
f.Sync()
//写入文件方法3
w := bufio.NewWriter(f)
//写入数据
w.WriteString("哈哈哈哈哈哈")
//刷新
w.Flush()
}
文件写入
package main
import "io/ioutil"
func main() {
var str = "File Writer"
ioutil.WriteFile("fw.txt", []byte(str), 0777)
}
文件读取
package main
import (
"io/ioutil"
"fmt"
)
func main() {
fr, _ := ioutil.ReadFile("fw.txt")
fmt.Println(string(fr))
}
读取文件的方法速度比较
package main
import (
"bufio"
"fmt"
"io"
"io/ioutil"
"os"
"time"
"net/http"
)
func read0(path string) string {
f, err := ioutil.ReadFile(path)
if err != nil {
fmt.Printf("%s\n", err)
panic(err)
}
return string(f)
}
func read1(path string) string {
fi, err := os.Open(path)
if err != nil {
panic(err)
}
defer fi.Close()
chunks := make([]byte, 1024, 1024)
buf := make([]byte, 1024)
for {
n, err := fi.Read(buf)
if err != nil && err != io.EOF {
panic(err)
}
if 0 == n {
break
}
chunks = append(chunks, buf[:n]...)
}
return string(chunks)
}
func read2(path string) string {
fi, err := os.Open(path)
if err != nil {
panic(err)
}
defer fi.Close()
r := bufio.NewReader(fi)
chunks := make([]byte, 1024, 1024)
buf := make([]byte, 1024)
for {
n, err := r.Read(buf)
if err != nil && err != io.EOF {
panic(err)
}
if 0 == n {
break
}
chunks = append(chunks, buf[:n]...)
}
return string(chunks)
}
func read3(path string) string {
fi, err := os.Open(path)
if err != nil {
panic(err)
}
defer fi.Close()
fd, err := ioutil.ReadAll(fi)
return string(fd)
}
func main() {
str, _ := http.Get("http://pic.sogou.com/pics/channel/getAllRecomPicByTag.jsp?category=%E5%A3%81%E7%BA%B8&tag=%E5%85%A8%E9%83%A8&start=0&len=100000")
html, _ := ioutil.ReadAll(str.Body)
ioutil.WriteFile("fw.json", html, 0777)
file := "fw.json"
start := time.Now()
read0(file)
t0 := time.Now()
fmt.Printf("Cost time %v\n", t0.Sub(start))
read1(file)
t1 := time.Now()
fmt.Printf("Cost time %v\n", t1.Sub(t0))
read2(file)
t2 := time.Now()
fmt.Printf("Cost time %v\n", t2.Sub(t1))
read3(file)
t3 := time.Now()
fmt.Printf("Cost time %v\n", t3.Sub(t2))
}
递归遍历目录
GO语言获取目录列表用 ioutil.ReadDir(),遍历目录用 filepath.Walk()
web 服务
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/", handler) // each request calls handler
log.Fatal(http.ListenAndServe("localhost:9512", nil))
}
// handler echoes the Path component of the request URL r.
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "你是我的眼")
}
Go 操作Excel文件
https://github.com/360EntSecGroup-Skylar/excelize
写入文件
package main
import (
"fmt"
"strconv"
"github.com/360EntSecGroup-Skylar/excelize"
)
func main() {
// 创建XMLS文件
xlsx := excelize.NewFile()
//循环写入数据
for i := 1; i < 1000; i++ {
//拼接字符串
//位子
axis := "B" + strconv.Itoa(i)
//在指定的位置写入数据
xlsx.SetCellValue("Sheet1", axis, 1024*i)
}
//创建sheet
index := xlsx.NewSheet("Sheet2")
//循环写入数据
for i := 1; i < 1000; i++ {
axis := "A" + strconv.Itoa(i)
//写入
xlsx.SetCellValue("Sheet2", axis, 1024*i)
}
//保存
xlsx.SetActiveSheet(index)
//保存文件
err := xlsx.SaveAs("hello.xlsx")
if err != nil {
fmt.Println(err)
}
}
将数字转化为字符串
strconv.Itoa(i)
读取Excel文件
package main
import (
"fmt"
"github.com/360EntSecGroup-Skylar/excelize"
"strconv"
)
func main() {
xlsx, err := excelize.OpenFile("1.xlsx")
if err != nil {
fmt.Println(err)
return
}
for i := 1; i < 100; i++ {
//读取
axisa := "A" + strconv.Itoa(i)
cella := xlsx.GetCellValue("06-08", axisa)
fmt.Println(cella)
axisb := "B" + strconv.Itoa(i)
cellb := xlsx.GetCellValue("06-08", axisb)
fmt.Println(cellb)
}
//读取指定sheet的所有信息
rows := xlsx.GetRows("06-08")
for _, row := range rows {
for _, colCell := range row {
fmt.Print(colCell, "\t")
}
fmt.Println()
}
}
Excel 写入图片
package main
import (
"fmt"
_ "image/gif"
_ "image/jpeg"
_ "image/png"
"github.com/360EntSecGroup-Skylar/excelize"
"strconv"
)
func main() {
xlsx, err := excelize.OpenFile("1.xlsx")
if err != nil {
fmt.Println(err)
return
}
for i := 1; i < 200; i++ {
if (i%23 == 0) {
xlsx.AddPicture("Sheet1", "A"+strconv.Itoa(i), "hai.png", `{"x_scale": 0.5, "y_scale": 0.5}`)
}
}
//xlsx.AddPicture("Sheet1", "A22", "hai.png", `{"x_scale": 0.5, "y_scale": 0.5}`)
//xlsx.AddPicture("Sheet1", "F1", "hai.png", `{"x_scale": 0.5, "y_scale": 0.5}`)
//
//
//xlsx.AddPicture("Sheet1", "H2", "hai.png", `{"x_offset": 15, "y_offset": 10, "print_obj": true, "lock_aspect_ratio": false, "locked": false}`)
err = xlsx.Save()
if err != nil {
fmt.Println(err)
}
}
MP3播放
package main
import (
"io/ioutil"
"github.com/hajimehoshi/oto"
"github.com/tosone/minimp3"
)
func main() {
var file, _ = ioutil.ReadFile("杨坤 - 那一天.mp3")
dec, data, _ := minimp3.DecodeFull(file)
player, _ := oto.NewPlayer(dec.SampleRate, dec.Channels, 2, 1024*8)
player.Write(data)
}
文件切割
package main
import (
"math"
"os"
"strconv"
)
const chunkSize int64 = 1024 * 1024 * 64
func main() {
// 获取文件的信息
fileInfo, _ := os.Stat("27_运算符(上).avi")
//计算每一个区块的大小
num := int(math.Ceil(float64(fileInfo.Size()) / float64(chunkSize)))
//打开文件
fi, _ := os.OpenFile("27_运算符(上).avi", os.O_RDONLY, os.ModePerm)
//
b := make([]byte, chunkSize)
//
var i int64 = 1
//
for ; i <= int64(num); i++ {
//移动指针
fi.Seek((i-1)*(chunkSize), 0)
if len(b) > int((fileInfo.Size() - (i-1)*chunkSize)) {
//分配内存
b = make([]byte, fileInfo.Size()-(i-1)*chunkSize)
}
//
fi.Read(b)
// 创建块的文件
f, _ := os.OpenFile(strconv.Itoa(int(i))+".db", os.O_CREATE|os.O_WRONLY, os.ModePerm)
//写入块文件
f.Write(b)
//关闭文件
f.Close()
}
}
文件合并
package main
import (
"os"
"fmt"
"strconv"
"io/ioutil"
)
func main() {
fii, _ := os.OpenFile("1.avi", os.O_CREATE|os.O_WRONLY|os.O_APPEND, os.ModePerm)
for i := 1; i <= 33; i++ {
f, err := os.OpenFile(strconv.Itoa(int(i))+".db", os.O_RDONLY, os.ModePerm)
if err != nil {
fmt.Println(err)
return
}
b, _ := ioutil.ReadAll(f)
fii.Write(b)
f.Close()
}
}
http 请求
package main
import (
"fmt"
"net/http"
"io"
"os"
"sync/atomic"
"runtime"
"time"
)
func main() {
//生成client 参数为默认
client := &http.Client{}
//生成要访问的url
url := "http://www.baidu.com"
//提交请求
reqest, _ := http.NewRequest("GET", url, nil)
//处理返回结果
response, _ := client.Do(reqest)
//将结果定位到标准输出 也可以直接打印出来 或者定位到其他地方进行相应的处理
stdout := os.Stdout
//输出请求体
_, _ = io.Copy(stdout, response.Body)
//返回的状态码
status := response.StatusCode
//打印输出状态
fmt.Println(status)
}
原子计数器
package main
import "fmt"
import "time"
import "sync/atomic"
import "runtime"
func main() {
// 我们使用一个无符号整型来代表一个永远为正整数的counter
var ops uint64 = 0
// 为了模拟并行更新,我们使用50个协程来每隔1毫秒来
// 增加一下counter值,注意这里的50协程里面的for循环,
// 也就是说如果主协程不退出,这些协程将永远运行下去
// 所以这个程序每次输出的值有可能不一样
for i := 0; i < 50; i++ {
go func() {
for {
// 为了能够保证counter值增加的原子性,我们使用
// atomic包中的AddUint64方法,将counter的地址和
// 需要增加的值传递给函数即可
atomic.AddUint64(&ops, 1)
// 允许其他的协程来处理
runtime.Gosched()
}
}()
}
//等待1秒中,让协程有时间运行一段时间
time.Sleep(time.Second)
// 为了能够在counter仍被其他协程更新值的同时安全访问counter值,
// 我们获取一个当前counter值的拷贝,这里就是opsFinal,需要把
// ops的地址传递给函数`LoadUint64`
opsFinal := atomic.LoadUint64(&ops)
fmt.Println("ops:", opsFinal)
}
信号
package main
import "fmt"
import "os"
import "os/signal"
import "syscall"
func main() {
// Go信号通知通过向一个channel发送``os.Signal`来实现。
// 我们将创建一个channel来接受这些通知,同时我们还用
// 一个channel来在程序可以退出的时候通知我们
sigs := make(chan os.Signal, 1)
done := make(chan bool, 1)
// `signal.Notify`在给定的channel上面注册该channel
// 可以接受的信号
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
// 这个goroutine阻塞等待信号的到来,当信号到来的时候,
// 输出该信号,然后通知程序可以结束了
go func() {
sig := <-sigs
fmt.Println()
fmt.Println(sig)
done <- true
}()
// 程序将等待接受信号,然后退出
fmt.Println("awaiting signal")
<-done
fmt.Println("exiting")
}
chan
package main
import (
"fmt"
)
func main() {
str1 := make(chan int, 2)
str2 := make(chan int, 2)
str1 <- 100
str2 <- 0xff
c1 := <-str1
c2 := <-str2
fmt.Printf("%d %d", c1, c2)
}
账单的写入
package main
import (
"fmt"
_ "image/gif"
_ "image/jpeg"
_ "image/png"
"github.com/360EntSecGroup-Skylar/excelize"
"strconv"
"io/ioutil"
)
var i = 1
var xlsx, _ = excelize.OpenFile("1.xlsx")
func main() {
readDir("F:\\初见文件\\初见\\支付测试")
xlsx.Save()
}
func readDir(dirPath string) {
flist, e := ioutil.ReadDir(dirPath)
if e != nil {
fmt.Println("Read file error")
return
}
for _, f := range flist {
if f.IsDir() {
readDir(dirPath + "/" + f.Name())
} else {
xlsx.AddPicture("Sheet1", "A"+strconv.Itoa(i), dirPath+"/"+f.Name(), `{"x_scale": 0.5, "y_scale": 0.5}`)
i += 49
}
}
}
文件重命名
// 文件重命名
syscall.Rename("新建文本文档.txt","ms.txt")
环境变量
//获取环境变量
fs := syscall.Environ()
//循环输出
for i = 0; i < len(fs); i++ {
fmt.Println(fs[i])
}
删除文件
os.Remove("ms2.txt")
连接MySQL
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
func main() {
db, err := sql.Open("mysql", "root:2018@/ms")//对应数据库的用户名和密码
defer db.Close()
if err != nil {
panic(err)
} else {
fmt.Println("success")
}
rows, err := db.Query("SELECT * from tb_user ")
if err != nil {
panic(err)
return
}
for rows.Next() {
var name int
err = rows.Scan(&name)
if err != nil {
panic(err)
}
fmt.Println(name)
}
}
Mysql 查询
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
func main() {
db, _ := sql.Open("mysql", "root:2018@/ms")
defer db.Close()
rows, _ := db.Query("select * from tb_user;")
defer rows.Close()
cloumns, _ := rows.Columns()
values := make([]sql.RawBytes, len(cloumns))
scanArgs := make([]interface{}, len(values))
for i := range values {
scanArgs[i] = &values[i]
}
for rows.Next() {
rows.Scan(scanArgs...)
var value string
for i, col := range values {
if col == nil {
value = "NULL"
} else {
value = string(col)
}
fmt.Println(cloumns[i], " --- ", value)
}
}
}
增删改
package main
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
func main() {
db, _ := sql.Open("mysql", "root:2018@/ms")
defer db.Close()
stmt, _ := db.Prepare("INSERT INTO ms VALUES ('MS-1GOGOGO')")
stmt.Exec()
}
正则表达式
package main
import "bytes"
import "fmt"
import "regexp"
func main() {
// 测试模式是否匹配字符串,括号里面的意思是
// 至少有一个a-z之间的字符存在
match, _ := regexp.MatchString("p([a-z]+)ch", "peach")
fmt.Println(match)
// 上面我们直接使用了字符串匹配的正则表达式,
// 但是对于其他的正则匹配任务,你需要使用
// `Compile`来使用一个优化过的正则对象
r, _ := regexp.Compile("p([a-z]+)ch")
// 正则结构体对象有很多方法可以使用,比如上面的例子
// 也可以像下面这么写
fmt.Println(r.MatchString("peach"))
// 这个方法检测字符串参数是否存在正则所约束的匹配
fmt.Println(r.FindString("peach punch"))
// 这个方法查找第一次匹配的索引,并返回匹配字符串
// 的起始索引和结束索引,而不是匹配的字符串
fmt.Println(r.FindStringIndex("peach punch"))
// 这个方法返回全局匹配的字符串和局部匹配的字符,比如
// 这里会返回匹配`p([a-z]+)ch`的字符串
// 和匹配`([a-z]+)`的字符串
fmt.Println(r.FindStringSubmatch("peach punch"))
// 和上面的方法一样,不同的是返回全局匹配和局部匹配的
// 起始索引和结束索引
fmt.Println(r.FindStringSubmatchIndex("peach punch"))
// 这个方法返回所有正则匹配的字符,不仅仅是第一个
fmt.Println(r.FindAllString("peach punch pinch", -1))
// 这个方法返回所有全局匹配和局部匹配的字符串起始索引
// 和结束索引
fmt.Println(r.FindAllStringSubmatchIndex("peach punch pinch", -1))
// 为这个方法提供一个正整数参数来限制匹配数量
fmt.Println(r.FindAllString("peach punch pinch", 2))
//上面我们都是用了诸如`MatchString`这样的方法,其实
// 我们也可以使用`[]byte`作为参数,并且使用`Match`
// 这样的方法名
fmt.Println(r.Match([]byte("peach")))
// 当使用正则表达式来创建常量的时候,你可以使用`MustCompile`
// 因为`Compile`返回两个值
r = regexp.MustCompile("p([a-z]+)ch")
fmt.Println(r)
// regexp包也可以用来将字符串的一部分替换为其他的值
fmt.Println(r.ReplaceAllString("a peach", "<fruit>"))
// `Func`变量可以让你将所有匹配的字符串都经过该函数处理
// 转变为所需要的值
in := []byte("a peach")
out := r.ReplaceAllFunc(in, bytes.ToUpper)
fmt.Println(string(out))
}
闭包
package main
import "fmt"
// 这个"intSeq"函数返回另外一个在intSeq内部定义的匿名函数,
// 这个返回的匿名函数包住了变量i,从而形成了一个闭包
func intSeq() func() int {
i := 0
return func() int {
i += 1
return i
}
}
func main() {
// 我们调用intSeq函数,并且把结果赋值给一个函数nextInt,
// 这个nextInt函数拥有自己的i变量,这个变量每次调用都被更新。
// 这里i的初始值是由intSeq调用的时候决定的。
nextInt := intSeq()
// 调用几次nextInt,看看闭包的效果
fmt.Println(nextInt())
fmt.Println(nextInt())
fmt.Println(nextInt())
// 为了确认闭包的状态是独立于intSeq函数的,再创建一个。
newInts := intSeq()
fmt.Println(newInts())
}
sync
package main
import (
"sync"
"time"
)
var m *sync.RWMutex
var val = 0
func main() {
m = new(sync.RWMutex)
go read(1)
go write(2)
go read(3)
time.Sleep(time.Second * 2)
}
func read(i int) {
m.RLock()
println("val: ", val)
m.RUnlock()
}
func write(i int) {
m.Lock()
val = 10
m.Unlock()
}
创建文件夹
package main
import "os"
func main() {
os.Mkdir("hello", 0777)
}
创建1024个文件夹,然后在删除
package main
import (
"os"
"strconv"
"time"
)
func main() {
for i := 0; i < 1024; i++ {
os.Mkdir("hello"+strconv.Itoa(i), 0777)
}
time.Sleep(time.Second * 30)
for i := 0; i < 1024; i++ {
os.Remove("hello" + strconv.Itoa(i))
}
}
简单的爬虫(抓取搜狗图片)
package main
import (
"net/http"
"strconv"
"io/ioutil"
"os"
"fmt"
)
var start = 0
var len = start + 10
func main() {
for {
var url = "http://pic.sogou.com/pics/channel/getAllRecomPicByTag.jsp?category=%E5%A3%81%E7%BA%B8&tag=%E5%85%A8%E9%83%A8&start=" + strconv.Itoa(start) + "&len=" + strconv.Itoa(len)
fmt.Println(url)
res, _ := http.Get(url)
reader, _ := ioutil.ReadAll(res.Body)
var filename = strconv.Itoa(start) + ".json"
os.Create(filename)
ioutil.WriteFile(filename, reader, 0777)
start = len
len = start + 10
if len > 1024 {
break
}
}
}
生成RSA 公钥和私钥
package main
import (
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"crypto/rand"
"flag"
"log"
"os"
)
func main() {
var bits int
flag.IntVar(&bits, "b", 2048, "密钥长度,默认为1024位")
if err := GenRsaKey(bits); err != nil {
log.Fatal("密钥文件生成失败!")
}
log.Println("密钥文件生成成功!")
}
func GenRsaKey(bits int) error {
// 生成私钥文件
privateKey, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return err
}
derStream := x509.MarshalPKCS1PrivateKey(privateKey)
block := &pem.Block{
Type: "私钥",
Bytes: derStream,
}
file, err := os.Create("private.pem")
if err != nil {
return err
}
err = pem.Encode(file, block)
if err != nil {
return err
}
// 生成公钥文件
publicKey := &privateKey.PublicKey
derPkix, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
return err
}
block = &pem.Block{
Type: "公钥",
Bytes: derPkix,
}
file, err = os.Create("public.pem")
if err != nil {
return err
}
err = pem.Encode(file, block)
if err != nil {
return err
}
return nil
}
测试RSA
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
_ "encoding/base64"
"encoding/pem"
"errors"
"flag"
"fmt"
"io/ioutil"
"os"
)
var decrypted string
var privateKey, publicKey []byte
func init() {
var err error
flag.StringVar(&decrypted, "d", "", "加密过的数据")
flag.Parse()
publicKey, err = ioutil.ReadFile("public.pem")
if err != nil {
os.Exit(-1)
}
privateKey, err = ioutil.ReadFile("private.pem")
if err != nil {
os.Exit(-1)
}
}
func main() {
var data []byte
var err error
data, err = RsaEncrypt([]byte("ms~go"))
if err != nil {
panic(err)
}
origData, err := RsaDecrypt(data)
if err != nil {
panic(err)
}
fmt.Println(string(origData))
}
// 加密
func RsaEncrypt(origData []byte) ([]byte, error) {
block, _ := pem.Decode(publicKey)
if block == nil {
return nil, errors.New("public key error")
}
pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
pub := pubInterface.(*rsa.PublicKey)
return rsa.EncryptPKCS1v15(rand.Reader, pub, origData)
}
// 解密
func RsaDecrypt(ciphertext []byte) ([]byte, error) {
block, _ := pem.Decode(privateKey)
if block == nil {
return nil, errors.New("private key error!")
}
priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext)
}
init 函数
package main
import "fmt"
func init() {
fmt.Println("Hello INIT")
}
func main() {
fmt.Println("main")
}
init 优先执行main函数
单例模式
package main
import (
"fmt"
)
var m *Manager
func GetInstance() *Manager {
if m == nil {
m = &Manager{}
}
return m
}
type Manager struct{}
func (p Manager) Manage() {
fmt.Println("manage...")
}
func main() {
fmt.Printf("%p\n", GetInstance())
fmt.Printf("%p\n", GetInstance())
fmt.Printf("%p\n", GetInstance())
fmt.Printf("%p\n", GetInstance())
fmt.Printf("%p\n", GetInstance())
}
单例加锁
package main
import (
"fmt"
"sync"
"time"
)
var m *Manager
var lock *sync.Mutex = &sync.Mutex{}
func GetInstance() *Manager {
lock.Lock()
defer lock.Unlock()
if m == nil {
m = &Manager{}
}
return m
}
type Manager struct{}
func (p Manager) Manage() {
fmt.Println("manage...")
}
func main() {
go func() { fmt.Printf("%p\n", GetInstance()) }()
go func() { fmt.Printf("%p\n", GetInstance()) }()
go func() { fmt.Printf("%p\n", GetInstance()) }()
go func() { fmt.Printf("%p\n", GetInstance()) }()
go func() { fmt.Printf("%p\n", GetInstance()) }()
fmt.Printf("%p\n", GetInstance())
fmt.Printf("%p\n", GetInstance())
fmt.Printf("%p\n", GetInstance())
fmt.Printf("%p\n", GetInstance())
time.Sleep(time.Second)
}
双重锁机制来提高效率
package main
import (
"fmt"
"sync"
"time"
)
var m *Manager
var lock *sync.Mutex = &sync.Mutex {}
func GetInstance() *Manager {
if m == nil {
lock.Lock()
defer lock.Unlock()
if m == nil {
m = &Manager {}
}
}
return m
}
type Manager struct {}
func (p Manager) Manage() {
fmt.Println("manage...")
}
func main() {
go func() { fmt.Printf("%p\n", GetInstance()) }()
go func() { fmt.Printf("%p\n", GetInstance()) }()
go func() { fmt.Printf("%p\n", GetInstance()) }()
go func() { fmt.Printf("%p\n", GetInstance()) }()
go func() { fmt.Printf("%p\n", GetInstance()) }()
fmt.Printf("%p\n", GetInstance())
fmt.Printf("%p\n", GetInstance())
fmt.Printf("%p\n", GetInstance())
fmt.Printf("%p\n", GetInstance())
time.Sleep(time.Second)
}
sync.Once
package main
import (
"fmt"
"sync"
"time"
)
var m *Manager
var once sync.Once
func GetInstance() *Manager {
once.Do(func() {
m = &Manager{}
})
return m
}
type Manager struct{}
func (p Manager) Manage() {
fmt.Println("manage...")
}
func main() {
go func() { fmt.Printf("%p\n", GetInstance()) }()
go func() { fmt.Printf("%p\n", GetInstance()) }()
go func() { fmt.Printf("%p\n", GetInstance()) }()
go func() { fmt.Printf("%p\n", GetInstance()) }()
go func() { fmt.Printf("%p\n", GetInstance()) }()
fmt.Printf("%p\n", GetInstance())
fmt.Printf("%p\n", GetInstance())
fmt.Printf("%p\n", GetInstance())
fmt.Printf("%p\n", GetInstance())
time.Sleep(time.Second)
}
文件拷贝
package main
import (
"fmt"
"io"
"os"
)
func main() {
CopyFile("1private.pem", "private.pem") // os.Args[1]为目标文件,os.Args[2]为源文件
fmt.Println("复制完成")
}
func CopyFile(dstName, srcName string) (written int64, err error) {
src, err := os.Open(srcName)
if err != nil {
return
}
defer src.Close()
dst, err := os.OpenFile(dstName, os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
return
}
defer dst.Close()
return io.Copy(dst, src)
}
有疑问加站长微信联系(非本文作者)