为何是Go语言

  • 类C的语法,这意味着Java、C#、JavaScript程序员能很快的上手
  • 有本身的垃圾回收机制
  • 跨平台、编译便可执行无需安装依赖环境
  • 支持反射

Go语言简介

Go 语言(或 Golang)起源于 2007 年,并在 2009 年正式对外发布。Go 是很是年轻的一门语言,它的主要目标是“兼具Python等动态语言的开发速度和 C/C++ 等编译型语言的性能与安全性”。html

数据类型

数据类型 说明
bool 布尔
string 字符串
int uint8,uint16,uint32,uint64,int8,int16,int32,int64
float float32,float64
byte byte

基本语法

HelloWorld

package main

import "fmt"

var name string

func init() {
  name = "world"
}

func main() {
  fmt.Println("hello " + name)
}
复制代码

咱们来执行一下:shell

$ go run main.go # main.go 为刚刚建立的那个文件的名称
$ hello world
复制代码

变量

变量声明

package main

import (
	"fmt"
)

func main() {
	var name string   // 声明
	name = "da'mao'mao" // 赋值
	fmt.Println(name)

	var age int = 18 // 声明并赋值
	fmt.Println(age)
}
复制代码

类型推断

package main

import (
	"fmt"
)

func main() {
	name := "damaomao"
	fmt.Println(name)

	age := 18
	fmt.Println(age)
}
复制代码

函数

try cachethrowerror

下面咱们经过一个示例来了解一下,在线运行示例:play.golang.org/p/PYy3ueuPF…bash

package main

import (
	"errors"
	"fmt"
	"strconv"
)

func main() {
	log1()

	log2("hello world")

	ret1 := add1(1, 1)
	fmt.Println("add1 result:" + strconv.Itoa(ret1))

	ret2, err := Add2(0, 1)
	if err == nil {
		fmt.Println("Add2 result:" + strconv.Itoa(ret2))
	} else {
		fmt.Println("Add2 error", err)
	}
}

// 私有、无入参、无返回值
func log1() {
	fmt.Println("execute func log1")
}

// 私有、入参、无返回值
func log2(msg string) {
	fmt.Println("execute func log2:" + msg)
}

// 私有、两个入参、一个返回值
func add1(count1, count2 int) int {
	total := count1 + count2
	fmt.Println("execute func add3, result=" + strconv.Itoa(total))
	return total
}

// Public、两个入参、多个返回值
func Add2(count1, count2 int) (int, error) {
	if count1 < 1 || count2 < 1 {
		return 0, errors.New("数量不能小于1")
	}
	total := count1 + count2
	return total, nil
}
复制代码

该示例输出结果为:架构

execute func log1
execute func log2:hello world
execute func add3, result=2
add1 result:2
Add2 error 数量不能小于1
复制代码
_
_, err := Add2(1, 2)
if err != nil {
  fmt.Println(err)
}	
复制代码

空白符特殊在于实际上返回值并无赋值,因此你能够随意将不一样类型的值赋值给他,而不会因为类型不一样而报错。异步

结构体

classstructclass
type User struct {
	Name   string
	Gender string
	Age    int
}
复制代码
User
user := User{
	Name:   "hahaha",
	Gender: "男",
	Age:    18, // 值得一提的是,最后的逗号是必须的,不然编译器会报错,这就是go的设计哲学之一,要求强一致性。
}
复制代码

结构体的属性能够在结构体内直接声明,那么如何为结构体声明函数(即Java中的方法)呢,咱们来看下下面的示例:在线运行示例:play.golang.org/p/01_cTu0Rz…

package main

import "fmt"

type User struct {
	Name   string
	Gender string
	Age    int
}

// 定义User的成员方法
func (u *User) addAge() {
	u.Age = u.Age + 1
}

func main() {
	user := User{
		Name:   "哈", // 名称
		Gender: "男", // 性别
		Age:    18,  // 值得一提的是,最后的逗号是必须的,不然编译器会报错,这就是go的设计哲学之一,要求强一致性。
	}
	user.addAge()
	fmt.Println(user.Age)
}
复制代码

指针类型和值类型

Java中值类型和引用类型都是定死的,int、double、float、long、byte、short、char、boolean为值类型,其余的都是引用类型,而Go语言中却不是这样。

在Go语言中:

&a&aa*b := &ab&a*b

下面咱们来看下例子,在线运行:play.golang.org/p/jxAKyVMjn…

package main

import (
	"fmt"
)

func main() {
	a := "123"
	b := &a

	fmt.Println(a)
	fmt.Println(b)
	fmt.Println(*b)
}

输出结果为:
123
0x40c128
123
复制代码

并发编程

Go语言的并发是基于 goroutine 的,goroutine 相似于线程,但并不是线程。能够将 goroutine 理解为一种虚拟线程。Go语言运行时会参与调度 goroutine,并将 goroutine 合理地分配到每一个 CPU 中,最大限度地使用CPU性能。

Go 程序从 main 包的 main() 函数开始,在程序启动时,Go 程序就会为 main() 函数建立一个默认的 goroutine。

下面咱们来看一个例子(在线演示:play.golang.org/p/U9U-qjuY0…

package main

import (
	"fmt"
	"time"
)

func main() {
	// 建立一个goroutine
	go runing()
	// 建立一个匿名的goroutine
	go func() {
		fmt.Println("喜特:" + time.Now().String())
	}()

	// 这里sleep一下是由于main方法若是执行完了,main该程序建立的全部goroutine都会退出
	time.Sleep(5 * time.Second)
}

func runing() {
	fmt.Println("法克:" + time.Now().String())
	time.Sleep(3 * time.Second)
}

输出:
法克:2009-11-10 23:00:00 +0000 UTC m=+0.000000001
喜特:2009-11-10 23:00:00 +0000 UTC m=+0.000000001
复制代码
喜特

若是说 goroutine 是Go语言程序的并发体的话,那么 channel 就是它们之间的通讯机制。一个 channel 是一个通讯机制,它可让一个 goroutine 经过它给另外一个 goroutine 发送值信息。每一个 channel 都有一个特殊的类型,也就是 channel 可发送数据的类型。一个能够发送 int 类型数据的 channel 通常写为 chan int。

下面咱们利用goroutine+channel来实现一个生产消费者模型,示例代码以下:(在线执行:play.golang.org/p/lqUBugLdU…

package main

import (
	"fmt"
	"time"
)

func main() {
	// 建立一个通道
	channel := make(chan int64)

	// 异步去生产
	go producer(channel)

	// 数据消费
	consumer(channel)
}

// 生产者
func producer(channel chan<- int64) {
	for {
		// 将数据写入通道
		channel <- time.Now().Unix()
		// 睡1秒钟
		time.Sleep(time.Second)
	}
}

// 消费者
func consumer(channel <-chan int64) {
	for {
		timestamp := <-channel
		fmt.Println(timestamp)
	}
}

输出为以下:(每秒钟打印一次)
1257894000
1257894001
1257894002
1257894003
复制代码

Java程序员以为很差用的地方

tag

参考

做者简介

大猫猫,互联网公司老码农、不折腾不舒服斯基,多年千万日活服务端研发和架构经验。

  • 码农俱乐部:mlog.club
码农俱乐部