网站建设的开发方式和费用,东台专业做网站,凡科建站小程序制作,织梦模板安装 一品资源网Golang简介
命令式语言静态类型语法标记类似于C#xff08;但括号较少且没有分号#xff09;#xff0c;结构类似Oberon-2编译为本机代码#xff08;没有JVM#xff09;没有类#xff0c;但有带有方法的结构接口没有实现继承。不过有type嵌入。函数是一等公民函数可以返…
Golang简介
命令式语言静态类型语法标记类似于C但括号较少且没有分号结构类似Oberon-2编译为本机代码没有JVM没有类但有带有方法的结构接口没有实现继承。不过有type嵌入。函数是一等公民函数可以返回多个值支持闭包指针但没有指针算术内置并发原语Goroutines和Channels
基本语法
你好世界
文件 hello.go
package mainimport fmtfunc main() {fmt.Println(Hello Go)
}
$ go run hello.go运算符
算术运算符
运算符描述加法-减法*乘法/除法%取余位与^位异或^位清除非左移右移
比较运算符
运算符描述等于!不等于小于小于等于大于大于等于
逻辑运算符
运算符描述逻辑与!逻辑非
其他
运算符描述取地址 / 创建指针*解引用指针-发送 / 接收操作符见下面的‘通道’部分
声明
类型在标识符之后
var foo int // declaration without initialization
var foo int 42 // declaration with initialization
var foo, bar int 42, 1302 // declare and init multiple vars at once
var foo 42 // type omitted, will be inferred
foo : 42 // shorthand, only in func bodies, omit var keyword, type is always implicit
const constant This is a constant// iota can be used for incrementing numbers, starting from 0
const (_ iotaabc 1 iotad
)fmt.Println(a, b) // 1 2 (0 is skipped)fmt.Println(c, d) // 8 16 (2^3, 2^4)函数
// a simple function
func functionName() {}// function with parameters (again, types go after identifiers)
func functionName(param1 string, param2 int) {}// multiple parameters of the same type
func functionName(param1, param2 int) {}// return type declaration
func functionName() int {return 42
}// Can return multiple values at once
func returnMulti() (int, string) {return 42, foobar
}
var x, str returnMulti()// Return multiple named results simply by return
func returnMulti2() (n int, s string) {n 42s foobar// n and s will be returnedreturn
}
var x, str returnMulti2()函数作为值和闭包
func main() {// assign a function to a nameadd : func(a, b int) int {return a b}// use the name to call the functionfmt.Println(add(3, 4))
}// Closures, lexically scoped: Functions can access values that were
// in scope when defining the function
func scope() func() int{outer_var : 2foo : func() int { return outer_var}return foo
}func another_scope() func() int{// wont compile because outer_var and foo not defined in this scopeouter_var 444return foo
}// Closures
func outer() (func() int, int) {outer_var : 2inner : func() int {outer_var 99 // outer_var from outer scope is mutated.return outer_var}inner()return inner, outer_var // return inner func and mutated outer_var 101
}可变参数函数
func main() {fmt.Println(adder(1, 2, 3)) // 6fmt.Println(adder(9, 9)) // 18nums : []int{10, 20, 30}fmt.Println(adder(nums...)) // 60
}// By using ... before the type name of the last parameter you can indicate that it takes zero or more of those parameters.
// The function is invoked like any other function except we can pass as many arguments as we want.
func adder(args ...int) int {total : 0for _, v : range args { // Iterates over the arguments whatever the number.total v}return total
}内置类型
boolstringint int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptrbyte // alias for uint8rune // alias for int32 ~ a character (Unicode code point) - very Vikingfloat32 float64complex64 complex128所有Go的预声明标识符都定义在builtin包中。
类型转换
var i int 42
var f float64 float64(i)
var u uint uint(f)// alternative syntax
i : 42
f : float64(i)
u : uint(f)包
在每个源文件的顶部声明包可执行文件位于main包中约定包的名称等于导入路径的最后一个部分导入路径math/rand 包rand大写标识符导出的可以从其他包中访问小写标识符私有的不能从其他包中访问
控制结构
判断
func main() {// Basic oneif x 10 {return x} else if x 10 {return 10} else {return -x}// You can put one statement before the conditionif a : b c; a 42 {return a} else {return a - 42}// Type assertion inside ifvar val interface{} fooif str, ok : val.(string); ok {fmt.Println(str)}
}循环 // Theres only for, no while, no untilfor i : 1; i 10; i {}for ; i 10; { // while - loop}for i 10 { // you can omit semicolons if there is only a condition}for { // you can omit the condition ~ while (true)}// use break/continue on current loop// use break/continue with label on outer loop
here:for i : 0; i 2; i {for j : i 1; j 3; j {if i 0 {continue here}fmt.Println(j)if j 2 {break}}}there:for i : 0; i 2; i {for j : i 1; j 3; j {if j 1 {continue}fmt.Println(j)if j 2 {break there}}}条件 // switch statementswitch operatingSystem {case darwin:fmt.Println(Mac OS Hipster)// cases break automatically, no fallthrough by defaultcase linux:fmt.Println(Linux Geek)default:// Windows, BSD, ...fmt.Println(Other)}// as with for and if, you can have an assignment statement before the switch valueswitch os : runtime.GOOS; os {case darwin: ...}// you can also make comparisons in switch casesnumber : 42switch {case number 42:fmt.Println(Smaller)case number 42:fmt.Println(Equal)case number 42:fmt.Println(Greater)}// cases can be presented in comma-separated listsvar char byte ?switch char {case , ?, , , #, , %:fmt.Println(Should escape)}数组, 切片, 遍历
数组
var a [10]int // declare an int array with length 10. Array length is part of the type!
a[3] 42 // set elements
i : a[3] // read elements// declare and initialize
var a [2]int{1, 2}
a : [2]int{1, 2} //shorthand
a : [...]int{1, 2} // elipsis - Compiler figures out array length切片
var a []int // declare a slice - similar to an array, but length is unspecified
var a []int {1, 2, 3, 4} // declare and initialize a slice (backed by the array given implicitly)
a : []int{1, 2, 3, 4} // shorthand
chars : []string{0:a, 2:c, 1: b} // [a, b, c]var b a[lo:hi] // creates a slice (view of the array) from index lo to hi-1
var b a[1:4] // slice from index 1 to 3
var b a[:3] // missing low index implies 0
var b a[3:] // missing high index implies len(a)
a append(a,17,3) // append items to slice a
c : append(a,b...) // concatenate slices a and b// create a slice with make
a make([]byte, 5, 5) // first arg length, second capacity
a make([]byte, 5) // capacity is optional// create a slice from an array
x : [3]string{Лайка, Белка, Стрелка}
s : x[:] // a slice referencing the storage of x数组和切片的操作
len(a) 返回数组/切片的长度。这是一个内置函数而不是数组的属性/方法。
// loop over an array/a slice
for i, e : range a {// i is the index, e the element
}// if you only need e:
for _, e : range a {// e is the element
}// ...and if you only need the index
for i : range a {
}// In Go pre-1.4, youll get a compiler error if youre not using i and e.
// Go 1.4 introduced a variable-free form, so that you can do this
for range time.Tick(time.Second) {// do it once a sec
}哈希表
m : make(map[string]int)
m[key] 42
fmt.Println(m[key])delete(m, key)elem, ok : m[key] // test if key key is present and retrieve it, if so// map literal
var m map[string]Vertex{Bell Labs: {40.68433, -74.39967},Google: {37.42202, -122.08408},
}// iterate over map content
for key, value : range m {
}结构体
Go中没有类只有结构体。结构体可以拥有方法。
// A struct is a type. Its also a collection of fields// Declaration
type Vertex struct {X, Y float64
}// Creating
var v Vertex{1, 2}
var v Vertex{X: 1, Y: 2} // Creates a struct by defining values with keys
var v []Vertex{{1,2},{5,2},{5,5}} // Initialize a slice of structs// Accessing members
v.X 4// You can declare methods on structs. The struct you want to declare the
// method on (the receiving type) comes between the the func keyword and
// the method name. The struct is copied on each method call(!)
func (v Vertex) Abs() float64 {return math.Sqrt(v.X*v.X v.Y*v.Y)
}// Call method
v.Abs()// For mutating methods, you need to use a pointer (see below) to the Struct
// as the type. With this, the struct value is not copied for the method call.
func (v *Vertex) add(n float64) {v.X nv.Y n
}匿名结构体 比使用 map[string]interface{} 更经济和更安全。
point : struct {X, Y int
}{1, 2}指针
p : Vertex{1, 2} // p is a Vertex
q : p // q is a pointer to a Vertex
r : Vertex{1, 2} // r is also a pointer to a Vertex// The type of a pointer to a Vertex is *Vertexvar s *Vertex new(Vertex) // new creates a pointer to a new struct instance接口
// interface declaration
type Awesomizer interface {Awesomize() string
}// types do *not* declare to implement interfaces
type Foo struct {}// instead, types implicitly satisfy an interface if they implement all required methods
func (foo Foo) Awesomize() string {return Awesome!
}嵌入
Go中没有子类化。相反有接口和结构体嵌入。
// ReadWriter implementations must satisfy both Reader and Writer
type ReadWriter interface {ReaderWriter
}// Server exposes all the methods that Logger has
type Server struct {Host stringPort int*log.Logger
}// initialize the embedded type the usual way
server : Server{localhost, 80, log.New(...)}// methods implemented on the embedded struct are passed through
server.Log(...) // calls server.Logger.Log(...)// the field name of the embedded type is its type name (in this case Logger)
var logger *log.Logger server.Logger错误
Go中没有异常处理。相反可能产生错误的函数只是声明了一个额外的返回值类型为error。这是error接口
// The error built-in interface type is the conventional interface for representing an error condition,
// with the nil value representing no error.
type error interface {Error() string
}这是一个示例
func sqrt(x float64) (float64, error) {if x 0 {return 0, errors.New(negative value)}return math.Sqrt(x), nil
}func main() {val, err : sqrt(-1)if err ! nil {// handle errorfmt.Println(err) // negative valuereturn}// All is good, use val.fmt.Println(val)
}并发
协程
Goroutines是轻量级线程由Go管理而不是操作系统线程。go f(a, b)启动一个新的goroutine来运行f假设f是一个函数。
// just a function (which can be later started as a goroutine)
func doStuff(s string) {
}func main() {// using a named function in a goroutinego doStuff(foobar)// using an anonymous inner function in a goroutinego func (x int) {// function body goes here}(42)
}通道
ch : make(chan int) // create a channel of type int
ch - 42 // Send a value to the channel ch.
v : -ch // Receive a value from ch// Non-buffered channels block. Read blocks when no value is available, write blocks until there is a read.// Create a buffered channel. Writing to a buffered channels does not block if less than buffer size unread values have been written.
ch : make(chan int, 100)close(ch) // closes the channel (only sender should close)// read from channel and test if it has been closed
v, ok : -ch// if ok is false, channel has been closed// Read from channel until it is closed
for i : range ch {fmt.Println(i)
}// select blocks on multiple channel operations, if one unblocks, the corresponding case is executed
func doStuff(channelOut, channelIn chan int) {select {case channelOut - 42:fmt.Println(We could write to channelOut!)case x : - channelIn:fmt.Println(We could read from channelIn)case -time.After(time.Second * 1):fmt.Println(timeout)}
}通道原理 向空通道发送会永远阻塞 var c chan string
c - Hello, World!
// fatal error: all goroutines are asleep - deadlock!从空通道接收会永远阻塞。 var c chan string
fmt.Println(-c)
// fatal error: all goroutines are asleep - deadlock!向已关闭的通道发送会引发恐慌。 var c make(chan string, 1)
c - Hello, World!
close(c)
c - Hello, Panic!
// panic: send on closed channel从已关闭的通道接收会立即返回零值。 var c make(chan int, 2)
c - 1
c - 2
close(c)
for i : 0; i 3; i {fmt.Printf(%d , -c)
}
// 1 2 0打印
fmt.Println(Hello, 你好, नमस्ते, Привет, ᎣᏏᏲ) // basic print, plus newline
p : struct { X, Y int }{ 17, 2 }
fmt.Println( My point:, p, x coord, p.X ) // print structs, ints, etc
s : fmt.Sprintln( My point:, p, x coord, p.X ) // print to string variablefmt.Printf(%d hex:%x bin:%b fp:%f sci:%e,17,17,17,17.0,17.0) // c-ish format
s2 : fmt.Sprintf( %d %f, 17, 17.0 ) // formatted print to string variablehellomsg : Hello in Chinese is 你好 (Ni Hao)Hello in Hindi is नमस्ते (Namaste)// multi-line string literal, using back-tick at beginning and end反射
类型切换
类型切换类似于常规的switch语句但类型切换中的情况指定要与给定接口值持有的值的类型进行比较的类型而不是值。
func do(i interface{}) {switch v : i.(type) {case int:fmt.Printf(Twice %v is %v\n, v, v*2)case string:fmt.Printf(%q is %v bytes long\n, v, len(v))default:fmt.Printf(I dont know about type %T!\n, v)}
}func main() {do(21)do(hello)do(true)
}片段
文件嵌入
Go程序可以使用embed包嵌入静态文件如下所示
package mainimport (embedlognet/http
)// content holds the static content (2 files) for the web server.
//go:embed a.txt b.txt
var content embed.FSfunc main() {http.Handle(/, http.FileServer(http.FS(content)))log.Fatal(http.ListenAndServe(:8080, nil))
}完整的Playground示例
HTTP服务器
package mainimport (fmtnet/http
)// define a type for the response
type Hello struct{}// let that type implement the ServeHTTP method (defined in interface http.Handler)
func (h Hello) ServeHTTP(w http.ResponseWriter, r *http.Request) {fmt.Fprint(w, Hello!)
}func main() {var h Hellohttp.ListenAndServe(localhost:4000, h)
}// Heres the method signature of http.ServeHTTP:
// type Handler interface {
// ServeHTTP(w http.ResponseWriter, r *http.Request)
// }