您当前的位置:网站首页>within,囊-女装拍摄,让美丽触手可及

within,囊-女装拍摄,让美丽触手可及

2019-05-21 07:41:28 投稿作者:admin 围观人数:217 评论人数:0次
写在前面: 本文是一个入门级教程,会从 Java 的视点来进行解读 go 的语法特性,并不会对一些问题进行深入探讨研讨。本文所述纯属个人见解,有不老练或许过错的当地欢迎批评指正。

为什么要放弃 Java,投靠 Go?

我从 2014 年开端触摸 Java,对 Java 这门言语有着一种母语情结。比较于 Cwithin,囊-女装拍照,让美丽触手可及,Java 具有面向对象、支撑跨渠道、废物收回等优异特性。且 Java 的强壮而老练的生态体系、丰厚的东西类等使 Java 能够支撑了许多大型的体系架构。所以被国内以阿里为代表的广阔企业用作编程主言语。

那么已然 Java 这么凶猛,为什么还需求学 go 呢?

我的答复是 :Go 比 Java 愈加简略、好用。

咱们来简略地看一段 Java 和 go 的代码,就拿完结并发来说


清楚明了,在代码简练度上 Go 能够说秒杀 Java。

当然,Go 言语除了简略、好用以外,也有其他的一些十分强壮的特性。

包括:

 1. 并发与协程
2. 依据音讯传递的通讯方梦见做爱式
3. 丰厚有用的内置数据类型
4. 函数多回来值
5. de簿本appfer 机制
6. 反射(reflect)
7. 高功用 HTTP Server

由于 Go 言语的这些优势,所以最近几年得到了很大的开展。许多新式技能包括 docker、kubernetes 等云端技能以及区块链等都是运用 Go 言语进行开发的。从这个意义上来说,Go 言语是比较“潮”的言语。技多不压身,那么就让咱们敞开 Go 言语之旅吧。

Go quick start

环境装置

装置环境比较简略,这儿就不赘述了,详细可参阅:http://www.runoob.com/go/go-environment.html

GoPath 和 GoRoot

经过上面教程的环境装置,你能够顺畅输出一个 hello world,那么这个进程中发作了8090新视觉什么呢?先来看代码

 package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}

运用过 Java 的同学应该是对 package 很熟悉了,Go 里边 package 的概念和 Java 是相似的。要生浚成 Go 可履行程序,有必要树立一个名为 main 的package,而且在该 package 中有必要包括一个名为 main() 的函数。"fmt" 也是一个包,那么这个包是怎样找到的呢?这儿就要引出 GoRoot 和 GoPath 了,GoPath 是 Go 的作业目录,GoRoot 是 Go 的装置目录。

运用 go env 指令能够查看 GoPath 和 GoRoot:


咱们履行的 fmt 这个包,就会去 GoRoot src 目录下去寻觅。内置的包和函数,如 fmt 、math、strings 等 会去从 src 目录去寻觅,那么假设我想运用 GitHub 上的开源包该怎样办呢?这儿就要提到 GoPath 了。

GoPath 目录约好有三个子目录

  • src:寄存源代码。依照 Go 言语约好,go run,go install 等指令默许会在此途径下履行;
  • pkg:寄存编译时生成的中心文件( * .a );
  • bin: 寄存编译后生成的可履行文件 ( 在项目内履行 go install,会在 bin 目录下生成一个可履行文件)。

当咱们要引证 GitHub 上的开源包时,比方运用 https://github.com/garyburd/redigo 这个包来用 golang 进行 redis 的操作。能够履行 go get https://github.com/garyburd/redigo 指令,将会在 GoPath 的 src 目录下生成一个 /github.com/garyburd/redigo 这样的目录结构。


即可在项目中像引证 fmt 包相同引证

 package main
import (
"fmt"
"github.com/garyburd/redigwithin,囊-女装拍照,让美丽触手可及o/redis"
)
func main() {
c, err := redis.Dial("tcp", "127.0.0.1:6379")
if err != nil {
fmt.Println("Connect to redis error", err)
return
}
fmt.Println("redis connect succ")
defer c.Close()
}

编译和运转

咱们先把随意找一个空目录,新建 test.go,贴上代码发动 redis ,履行 go run test.go,即可呈现 "redis connect succ" , 程序履行成功。

Go 指令

Go 供给了许多指令,包括打包、格局化代码、文档生成、下载第三方包等等许多功用,咱们在指令行东西上履行 go --help ,如下:


这儿要点介绍几个常用的指令

  • go run
  • 编译并履行,只能作用于指令源码文件,一般用于开发中快速测验。上文咱们经过履行 go run test.go ,完结了程序的编译运转。
  • go build 编译代码包或许源码文件。假设带上代码包名,则表明编译指定的代码包;假设带上源码文件,则表明编译指定源码文件。
  • go get 下载第三方代码包并编译装置 ,需求留意的是,它会下载装置到 GOPATH 环境变量装备的榜首个作业区中。上文咱们在运用 Go 衔接 redis 时,经过 go get https://github.com/garyburd/redigo 指令,将 redis 包下载到 GoPath 的 src 牵手目录下并进行编译装置。然后在代码中进行 import "github.com/garyburd/redigo/redis" 这个包则完结了导入。
  • go install 这个指令用于编译装置,能够作用于 main 包和非 main 包,然后将编译后的生成的履行文件寄存到工程的 bin 目录下,将生成的归档文件(即静态链接库)寄存到工程的 pkg 目录下。运用办法相似于 go build,能够在某个代码包目录下直接运用,也能够指定代码包运用。
  • 比方在咱们刚刚履行 go get https://github.com/garyburd/redigo 进行了 redis 包的编译装置。假设咱们不运用 go get,而是经过下载 zip 压缩包的办法,在 GoPath 的 src 目录下树立解压,构成 github.com/garyburd/redigo 的目录结构 ,然后履行 go install github.com/garyburd/redigo/redis ,咱们会发现在 GoPath 的 pkg 目录下会生成一个 这样的目录 /darwin_amd64/github.com/garyburd/redigo,redigo 目录下会生成一个 redis.a 的文件。
  • .a文件是编译进程中生成的,每个package都会生成对应的.a文件,Go在编译的时分先判别package的源码是否有改动,假设没有的话,就不再从头编译.a文件,这样能够加快速度。
  • go env 用于打印GO言语的环境信息,如 GOPATH 是作业区目录,GOROOT 是 GO 言语装置目录,GOBIN 是经过 go install 指令生成可履行文件的寄存目录(默许是其时作业区的 bin 目录下),GOEXE within,囊-女装拍照,让美丽触手可及为生成可履行文件的后缀
  • go vet 代码静态查看东西,如 go vet test.go。

完结 Java 语法 到 Go 语法的敏捷切换

声明与赋值

数据类型

和 Java 相似,Go 也有根本数据类型和引证数据类型。

根本数据类型

  • 布尔型:Java 声明用 boolean, Go 用 bool。
  • 整型:Go 里边有 int8 int16 int32 uint64 ,别离对应 Java 中的 byte short int long,一起 Go 里边还有专门 表明无符号数的 uint8 uint 16 uint32 uint64。
  • 浮点型:Go 里边 有 float32 float64 别离对应 Java 的 float 和 double。
  • 字符串类型:Go 和 Java 相同,都是 string。
  • 派生类型:包括 指针类型(Pointer)、数组类型、结构化类型(struct)、Channel 类型、函数类型、切片类型、接口类型(interface)、Map 类型 等。

变量声明赋值

Go 言语变量声明赋值有三种办法

先声明、后赋值

例如 :

 var name string
name = "diuge"

Go 言语顶用 var 声明变量,Java 言语中是以 分号 “ ; ” 进行句子切割,所以行末会有分号,而 Go 中没有.

Java 中变量声明是类型在变量前面,例如 string name , 但 Go 中相反,是变量在类型前,例如上文 var name swithin,囊-女装拍照,让美丽触手可及tring。

声明而且赋值

var name = "diuge"

编译器会依据值自行断定变量类型

运用 " := " 声明并赋值

name := "diuge"

这儿省掉 var 关键字

条件、循环句子

条件句子

Go 言语中 if 句子的语法如下:

 if 布尔表达式 {
/* 在布尔表达式为 true 时履行 */
}

需求留意的是,Go 中条件句子,if 没有括号,例如

 if a < 20 {
/* 假设条件为 true 则履行以下句子 */
fmt.Printf("a 小于 20\n" )
}

此外,if 还有别的一种办法,它包括一个 statement 可选句子部分,该组件在条件判别之前运转。它的语法是

 if statement; condition { 
}

例如:

 if a := 10 ; a < 20 {
/* 假设条件为 true 则履行以下句子 */
fmt.Printf("a 小于 20\n" )
}

循环句子

与 Java 不同的是,Go 言语只供给了 for 循环,没有 while 循环。

可是在 Go 中,能够运用 for 循环完结 Java while 循环的作用。

Go 言语的 For 循环有 3 种办法,只需其间的一种运用分号。

榜首种 :和 Java 的 for 语法相似,语法格局如下 :

 for init; condition; post { 
}
init: 一般为赋值表达式,给操控变量赋初值;
condition: 联系表达式或逻辑表达式,循环操控条件;
post: 一般为赋值表达式,给操控变量增量或减量。
例如 : for i :=0 ; i < 10 ; i ++ {
fmt.Println("i = " + i)
}

这儿是不是很熟悉? 跟 Java 仅有不相同的当地在于 Go 中 for 循环没有小括号。

第二种 :和 Java while 循环 相似,语法格局如下 :

 for condition { }
例如 :
for 0 == 0 {}
for true {}

第三种 : 死循环,相似 while (true) {} , 语法格局如下:

 for { }

反常处理

学 Java 的咱们或许都知道,Java 中有 exception 的 try — catch — finally 反常捕获机制 ,Go 言语中一般不选用这种反常捕获机制,而是经过下面几种办法进行反常处理。

error 接口

Go 言语经过内置的过错接口供给了十分简略的过错处理机制。

error 类型是一个接口类型,这是它的界说:

 type error interface {
Error() string
}

运用 errors.New () 能够回来一个 error 信息 例如 :

 func checkParam(username string, password string) error {
if username == "" || password == "" {
return errors.New("params error")
}
}

一般来说, error 是 Go 言语中最常见的处理过错的办法,经过回来 error,处理 error, 发作相似 Java exception 的作用。

defer 句子

在 Go 言语中,能够运用关键字defer向函数注册退出调用,即主调函数退出时,defer后的函数才会被调用

defer 句子的作用是不论程序是否呈现反常,均在函数退出时主动履行相关代码。(相当于 Java 中的 finally

例如 :

 func main() {
for i := 0; i < 5; i++ {
defer fmt.Println(i)
}
}
其履行成果为 :
4
3
2
1
0

所以,咱们在进行数据库衔接、文件、锁 操作时 ,一般都会运用 defer 句子进行数据库衔接的开释,开释文件句柄和锁的开释。

panic-recover 机制

学过 Java 的同学都知道,Java 中反常分为运转within,囊-女装拍照,让美丽触手可及时反常和非运转时反常。咱们在上文提到能够在办法中抛出 error 过错来完结反常的捕获, 武穴气候error 只能针对预期内的过错,由于你是预判这段程序或许呈现 反常逻辑,才会去主动调用 errors.New () 生成一个 error 。可是关于一个办法来说,咱们不或许预判到一切的反常情况,那假设某一个躲藏 bug 导致程序溃散了怎样办呢?这儿就需求引进 panic-recover 机制了。

假设代码运转时反常溃散了,此刻 Go 会主动 panic,Go 的每次 panic 都是十分耗费功用的,且 Go 是单线程,所以,咱们应该尽量去避免 运用 panic。

panic () 是一个内建函数,能够中止原有的操控流程,进入一个令人 panic (惊惧 ,即 Java 中的反常)的流程中。当函数 F 调用 panic,函数 F的履行被中止,可是 F 中的推迟函数(有必要是在 panic 之前的已加载的 defer )会正常履行,然后 F 回来到调用它的当地。在调用的当地,F 的行为就像调用了panic。这一进程持续向上,直到发作 panic 的 goroutine 中一切调用的函数回来,此刻程序退出。反常能够直接调用 panic 发作。也能够由运转时过错发作,例如拜访越界的数组。

recover () 是一个内建的函数,能够让进入令人惊惧的流程中的 goroutine 康复过来。recover 仅在推迟函数中有用。在正常的履行进程中,调用 recover 会回来 nil ,而且没有其它任何作用。假设其时 goroutine 堕入 panic ,调用 recover 能够捕获到 panic 的输入值,而且康复正常的履行。

一般情况下,recover () 应该在一个运用 defer 关键字的函数中履行以有用截取过错处理流程。假设没有在发作反常的 goroutine 中清晰调用康复进程(运用 recover 关键字),会导致该 goroutine 所属的进程打印反常信息后直接退出。

这儿结合自界说的 error 类型给出一个运用 panic 和 recover 的完好比方:

 package main
import (
"fmt"
)
//界说除法运算函数
func Devide(num1, num2 int) int {
if num2 == 0 {
panic("num cannot be 0")
} else {
return num1 / num2
}
}
func main() {
var a, b int
fmt.Scanf("%d %d", &a, &b)
defer func() {
if r := recover(); r != nil {
fmt.Printf("panic的内容%v\n", r)
}
}()
rs := Devide(a, b)
fmt.Println("成果是:", rs)
}

Go 言语特性

这儿指的特性是数据类型以及语法上的特性,不上升到归纳层次

函数

在 Java 中,函数是只能有单一回来值的lazada,可是在 Go 中,函数能够支撑多回来值。

例如 :

 func swap ( x string , y string ) ( string , string ){
return y , x
}

Go 指针

Java 是不支撑指针类型的,可是学过 C 的同学或许对指针有或多或少的了解,Go 言语也是支撑指针类型的。

咱们都知道,变量是一种运用方便的占位符,用于引证核算机内存地址。Go 言语的取地址符是 &,放到一个变量前运用就会回来相应变量的内存地址。

 package main
import "fmt"
func main() {
var a int = 10
fmt.Printf("变量的地址: %x\n", &a )
}
上面程序的输出成果为:
变量的地址: 20818a220

指针声明格局如下:

 var var_name *var-type

var-type 为指针类型,var_name 为指针变量名,* 号用于指定变量是作为一个指针。以下是有用的指针声明:

 var ip *int /* 指向整型*/
var fp *float32 /* 指向浮点型 */

在指针类型前面加上 * 号(前缀)即可获取指针所指向的内容。

 package main
import "fmt"
func main() {
var a int= 20 /* 声明实践变量 */
var ip *int /* 声明指针变量 */
ip = &a /* 指针变量的存储地址 */
fmt.Printf("a 变量的地址是: %x\n", &a )
/* 指针变量的存储地址 */
fmt.Printf("ip 变量贮存的指针地址: %x\n", ip )
/* 运用指针拜访值 */
fmt.Printf("*ip 变量的值: %d\n", *ip )
}

指针的操作比较复杂,这儿也仅仅对指针进行了简略的介绍,界说和程序都来自第三方网站,所以咱们想更多了解指针的话能够自行研讨一下,这儿不赘述。

**结构体 **

Go 言语中结构体相似 Java 中的类 ( class )**

例如, Java 中对一个 Person 类的界说如下 :

 class Person {
string name;
int age;
}

在 Go 言语中, 用结构体 ( struct ) 表明如下 :

 type Person struct {
name string
age int
濮建芳}

**切片 **

Java 中的数组长度在声明时就现已固定了,可是 Go 供给了一种相似 “ 动态数组 ” 结构的数据类型,这种类型便是切片 slice。

slice 的实质是一个数据结构,完结了对数组操作的封装。

切片 slice 的声明语法如下 :

 var identifier []type

你能够声明一个 int32 类型的 slice

 var array []int32

你会发现 slice 和数组的声明语法是不同的。

Go 言语中声明数组时,是需求指定长度的, 比方 :

 var array [10] int32

初始化操作也不相同,对 slice 的初始化是运用 make 初始化

 array = make ( []int32 , 10 )

而对数组的初始化是

 array = [10] int32 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

对 slice 的操作是 Go 言语中最常用的操作之一,包括 :剃刀边际

  • append : 完结对 slice 元素的增加 例如 :
 array := make ( []int32 , 10 )
array = append ( array, 1 )
array = append ( array, 2 )
  • 截取 : 能够经过设置下限及上限来设置截取切片 [lower-bound:upper-bound],实例如下:
 package main
import "fmt"
func main() {
/* 创立切片 */
numbers := []int{0,1,2,3,4,5,6,7,8}
/* 打印原始切片 */
fmt.Println("numbers ==", numbers)
/* 打印子切片从索引1(包括) 到索引4(不包括)*/
fmt.Println("numbers[1:4] ==", numbers[1:4])
/* 默许下限为 0*/
fmt.Println("numbers[:3] ==", numbers[:3])
/* 默许上限为 len(s)*/
fmt.Println("numbers[4:] ==", numbers[4:])
}
func printSlice(x []int){
fmt.Printf("len=%d slice=%v \n" , len(x) , x)
}
履行以上代码输出成果为:
numbers == [0 1 2 3 4 5 6 7 8]
numbers[1:4] == [1 2 3]
numbers[:3] == [0 1 2]
numbers[4:] == [4 5 6 7 8]
  • 获取切片长度 : 经过 len 办法,能够获取 slice 长度
 len ( slice )
  • 遍历 : 经过 range 关键字进行遍历,range 遍历是 Go 中特有的一种遍历办法,除了能够对 slice 进行遍历,还能够对 数组、map、string 字符串 等进行遍历。例如 :
 package main
import "fmt"
func main() {
//这是咱们运用range去求一个slice的和。运用数组跟这个很相似
nums := []int{2, 3, 4}
sum := 0
for _, num := range nums {
sum += num
}
fmt.Println("sum:", sum)
//在数组上运用range将传入index和值两个变量。上面那个比方咱们不需求运用该元素的序号,所以咱们运用空白符"_"省掉了。有时侯咱们的确需求知道它的索引。
for i, num := range nums {
if num == 3 {
fmt.Println("index:", i)
}
}
//range也能够用在map的键值对上。
kvs := map[string]string{"a": "apple", "b": "banana"}
for k, v := range kvs {
fmt.Printf("%s -> %s\n", k, v)
}
//range也能够用来枚举Unicode字符串。榜首个参数是字符的索引,第二个是字符(Unicode的值)自身。
for i, c := range "go" {
fmt亦舒.Println(i, c)
}
}

**并发 **

之前提到了,比较于 Java ,Go 是天然支撑并发的

在 go 言语中,每一个线程咱们把它叫做 goroutine

goroutine 是轻量级线程,goroutine 的调度是由 Golang 运转时进行办理的。

goroutine 语法格局:

go 函数名( 参数列表 ),例如:

 go f (x, y, z)

表明新开一个线程 履行 f (x , y , z) 这个办法。

strong text 更多并发的知识点下文会持续介绍,这儿不再赘述。

Java 面向对象特性在 Go 中是怎么完结的

咱们知道 Java 这门言语的盛行跟 它面向对象的特性是分不开的。那么 Java 的封装、承继、多态 在 Go 中是怎么完结的呢?

封装

Java 中的封装主要是经过拜访权限操控完结的。


在 Go 言语中,并没有 public ,private 这些权限操控符。那么 go 是怎么完结 结构体的封装的呢 ?

在 Go 言语中,是经过约好来完结权限操控的。变量和办法都恪守驼峰式命名。变量和办法的首字母大写,相当于 public,变量和办法的首字母小写,相当于 private。同一个包中拜访,相当于 default ,由于 Go70kg 言语没有承继,所以也没有 protected 权限。

承继

上面刚提到,Go 言语是没有承继的。可是 Go 言语能够经过结构体之间的组合来完结相似 Java 中承继的作用。

假设把 Go 中 struct 看做 Java 中的类,在 struct 中能够包括其他的struct,承继内部 struct 的办法和变量,一起能够重写,代码如下:

 package main
import "fmt"
type oo struct {
inner
ss1 string
ss2 int
ss3 bool
}
type inner struct {
ss4 string
}
func (i *inner) testMethod () {
fmt.Println("testMethod is called!!!")
}
func main() {
oo1 := new(oo)
fmt.Println("ss4无值:"+oo1.ss4)
oo1.ss4 = "abc"
fmt.Println("ss4已赋值"+oo1.ss4)
oo1.testMethod()//承继调用
oo1.inner.testMethod()//承继调用 这儿也能够重写
}

多态

Java 中的多态是经过 extends class 或许 implements interface 完结的,在 Go 中既没有 extends,也没有 implements ,那么 Go 中是怎么完结多态within,囊-女装拍照,让美丽触手可及的呢 ?

咱们来看以下代码,Girl 和 Boy 都完结了 Person 。 在 Go 言语中,只需某个 struct 完结了某个 interface 的一切办法,那么咱们就以为这个 struct 完结了这个类(相当于 Java 中的implements)。

 package main
import (
"fmt"
)
type Person interface {
Sing ()
}
type Girl struct {
Name string
}
type Boy struct {
Name string
}
func (this *Girl) Sing () {
fmt.Println("Hi, I am " + this.Name)
}
func (this *Boy) Sing () {
fmt.Println("Hi, I am " + this.Name)
}
func main() {
g := &Girl{"Lucy"}
b := &Boy{"Dave"}
p := map[int]Person{}
p[0] = g
p[1] = b
for _, v := range p {
v.Sing()
}
}

Go 并发

Java 中的并发是经过承继 Thread 类或许完结 Runnable 接口来完结的。咱们前面说过,Go 并发经过 Go 关刘伯希键字就能够完结,go f (x, y, z) 的办法即能够经过 新开 goroutine 完结 Go 并发。那么 goroutine 之间是怎么进行通讯与同步的呢

channel

channel 是 goroutine 之间通讯的一种办法,能够类比成 Unix 中的进程的通讯办法管道。

能够用 channel 操作符 <- 对其发送或许接纳值。

 ch <- v // 将 v 送入 channel ch。
v := <-ch // 从 ch 接纳,而且赋值给 v。
(“箭头”便是数据流的方向。)

和 map 与 slice 相同,channel 运用前有必要创立:

 ch := make(chan int)

默许情况下,在另一端准备好之前,发送和接纳都会堵塞。在线测速这使得 goroutine 能够在没有清晰的锁或竞态疝气手术变量的情况下进行同步。

例如 :

 package main
import "fmt"
func sum(a []int, c chan乐正绫 int) {
sum := 0
for _, v := range a {
sum += v
}
c <- sum // 将和送入 c
}
func main() {
a := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(a[:len(a)/2], c)
go sum(a[len(a)/2:], c)
x, y := <-c, <-c // 从 c 中获取
fmt.Println(x, y, x+y)
}

channel 能够是带缓冲的。为 make 供给第二个参数作为缓冲长度来初始化一个缓冲 channel:

 ch := make(chan int, 100)

向缓冲 channel 发送数据的时分,只需在缓冲区满的时分才会堵塞。当缓冲区清空的时分承受堵塞。

一起,能够运用 close(c) 来封闭一个 channel。

select

select 句子使得一个 goroutine 在多个通讯操作上等候。

select 会堵塞,直到条件分支中的某个能够持续履行,这时就会履行那个条件分支。当多个都准备好的时分,会随机挑选一个。

当 select 中的其他条件分支都没有准备好的时分,default 分支会被履行。

例如 :

 package main
import (
"fmt"
"time"
)
func main() {
tick := time.Tick(100 * time.Millisecond)
boom := time.After(500 * time.Millisecond)
for {
select {
case <-tick:
fmt.Println("tick.")
case <-boom:
fmt.Println("BOOM!")
return
default:
fmt.Println(" .")
time.Sleep(50 * time.Millisecond)
}
}
}

这儿只介绍一种互斥锁,其他类型的锁读者能够自行了解。

互斥锁用 var mutex sync.Mutex 声明 ,经过 mutex.Lock() 进行加锁,经过 mutex.Unlock() 进行解锁。

例如 :

 func main() {
var common int = 100
var mutex sync.Mutex
for {
go func() {
mutex.Lock()
if common > 0 {
common --
fmt.Println(common)
}
mutex.Unlock()
}()
}
}

这儿 common 是对一切线程都可见的同享内存,所以对common 的操作需求加锁。咱们发现 Go 言语的互斥锁的运用是十分简略的,这也契合 Go 言语的规划理念。

Go RPC 调用

RPC 最常用的办法仍是走 HTTP 协议,能够有 GET 和 POST 两种办法。

GET

这儿贴上一个简略的发送 HTTP Get 恳求的代码:

 package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
// 生成默许client
client := &http.Client{}
// 生成要拜访的url
url := "http://www.baidu.com"
// 结构恳求
request, err := http.NewRequest("GET", url, nil)
if err != nil {
fmt.Println("new request error : " + err.Error())
}
// 处理回来成果
response, err := client.Do(request)
within,囊-女装拍照,让美丽触手可及// 处理过错
if err != nil {
fmt.Println("do request error : " + err.E仲浩林rror ())
}
body, err := ioutil.ReadAll ( resp.Body )
fmt.Println( string (body) )
}

POST

比较简略,直接贴代码 :

 func request () {
client := &http.Client{}
req, err := h苹果泥ttp.NewRequest("POST", "www.baidu.com", strings.NewReader(""))
if err != nil {
// handle error
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Cookie", "uin=1812672342")
resp, err := client.Do(req)
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
// handle error
}
fmt.Println(string(body))
}

一个小 Demo:用 Go 言语完结抽奖体系

附送上一个小 demo ,运用 Go 写的,十分简略,原本奖品应该用 redis 存储,这儿偷闲了一下,经过装备文件初始化了。

讲一下 抽奖算法是参阅 微信渠道的抽奖算法:https://www.xuanfengge.com/luck-draw.html(能够避免奖品被很快抽完,一起确保每个人的抽奖概率是相同的)。这儿用 Go 重写了抽奖算法,如下:

 func GetAward(awardBatches []AwardBatch) (AwardBatch, error) {
startTime , _ := ParseStringToTime(conf.Award.StartTime)
endTime , _ := ParseStringToTime(conf.Award.EndTime)
award , err := RandomGetAwardBatch(awardBatches)
if err != nil {
return 小岳岳AwardBatch{}, err
}
totalAmount := award.GetTotalAmount()
totalBalance := award.GetTotalBalance()
upd张晓谦ateTime := award.GetUpdateTime()
detaTime := (endTime - startTime) / totalAmount
currentTime := time.Now().Unix()
r := rand.New(rand.NewSource(updateTime))
// 核算下一个奖品的开释时刻
releaseTime := startTime + (totalAmount - totalBalance) * detaTime + int64(r.Int()) % detaTime
fmt.Println("releaseTime : " + fmt.Sprintf("%d", releaseTime) + " currentTime : " + fmt.Sprintf("%d",currentTime))
if (currentTime < releaseTime) {
return AwardBatch{} , errors.New(" currentTime not in award release period ")
}
return award, nil
}
func RandomGetAwardBatch(awardBatches []AwardBatch) ( AwardBatch , error ) {
if len(awardBatches) == 0 {
return AwardBatch{} , errors.New("empty param awardBatches")
}
weight := int64(0)
for _, awardBatch := range awardBatches {
weight += awardBatch.GetTotalBalance()
}
if weight == 0 {
return AwardBatch{}, errors.New("weight is 0")
}
r := rand.New(rand.NewSource(weight))
num := r.Int63n(weight)
for _, awardBatch := range awardBatches {
num -= awardBatch.GetTotalBalance()
if num < 0 {
return awardBatch , nil
}
}
return AwardBatch{}, errors.New("randomGetAwardBatch should shoot at least one batch")
}

我把它放在了 GitHub 上 https://github.com/diubrother/award,能够用来当作 Go 入门级的一个小 demo。

我的 Go 入门之路

为什么说 7 天转型呢?由于我其时便是用了 7 天左右。写 Go 的榜首行代码时,很不习惯,无论是变量的命名,仍是没有行末分隔符,以及 Go 最让我不习惯的一点是 数据类型只能显现转化,举个比方,假设不显现把 uint 32 转成 int64 或许 uint64 ,你的程序是永久编译不经过的。

个人觉得,学一门言语最快仍是从运用开端,语法看个一两天,一定要对着用例 code ,对语法有个根本的形象就能够开端写需求或许功用了。能够尝试着写一些小的需求。我其时便是经过一个小的事务需求,直接对着他人的代码抄,然后抄个两三天,把你的代码编译、调试、测验、上线等整套流程走完,根本上就算是开始上手了。

the end
女装拍摄,让美丽触手可及