威尼斯手机平台-电子正规官网登录首页

热门关键词: 威尼斯手机平台,威尼斯登录首页,威尼斯正规官网
具体如下,bug、解决小故障、修复可用性以及性能方面的问题
分类:项目

GoLand 2019.2.2 bug-fix 版本已发布,此版本主要修复了一些性能和可用性、重构功能和代码格式化相关的问题。具体如下:

一个月前 GoLand 发布了 2019.3 的 Roadmap,据当时的介绍,此版本将会修复 bug、解决小故障、修复可用性以及性能方面的问题。不过目前看来,GoLand 2019.3 似乎还增加了不少新特性。

该文章是我在极客学院-go入门指南上学习总结的,大部分是自己感觉有必要记录的东西我才会ctrlcv的,感谢极客学院的无私分享,望勿赞

  • go中的interface
package main

import "fmt"

type Shaper interface {
    Area() float32
}

type Square struct {
    side float32
}

func (sq *Square) Area() float32 {
    return sq.side * sq.side
}

func main() {
    sq1 := new(Square)
    sq1.side = 5

    var areaIntf Shaper    //这里声明了一个接口  这叫接口示例
    areaIntf = sq1    // 直接转换成接口
    // shorter,without separate declaration:
    // areaIntf := Shaper(sq1)
    // or even:
    // areaIntf := sq1
    fmt.Printf("The square has area: %fn", areaIntf.Area())    //这里就直接使用了

}

进击版

package main

import "fmt"

type Shaper interface {
    Area() float32
}

type Square struct {
    side float32
}

func (sq *Square) Area() float32 {
    return sq.side * sq.side
}

type Rectangle struct {
    length, width float32
}

func (r Rectangle) Area() float32 {
    return r.length * r.width
}

func main() {

    r := Rectangle{5, 3} // Area() of Rectangle needs a value
    q := &Square{5}      // Area() of Square needs a pointer
    // shapes := []Shaper{Shaper(r), Shaper(q)}
    // or shorter
    shapes := []Shaper{r, q}    //都是Shaper接口,这个列表里面都是Shaper接口。
    fmt.Println("Looping through shapes for area ...")
    for n, _ := range shapes {    //但是这里的输出很喜人,因为是按照不同的类型输出不同的方法,接口的威力在这里显现,不过我咋也没感觉多大威力呢
        fmt.Println("Shape details: ", shapes[n])
        fmt.Println("Area of this shape is: ", shapes[n].Area())
    }
}

//输出  输出可以看出端倪,你看都是for循环,但是最终的结果是两种不同的操作,多么溜的操作。
Looping through shapes for area ...
Shape details:  {5 3}
Area of this shape is:  15
Shape details:  &{5}
Area of this shape is:  25

进击进击版

有两个类型 stockPosition 和 car,它们都有一个 getValue() 方法,我们可以定义一个具有此方法的接口 valuable。接着定义一个使用 valuable 类型作为参数的函数 showValue(),所有实现了 valuable 接口的类型都可以用这个函数

package main

import "fmt"

type stockPosition struct {
    ticker     string
    sharePrice float32
    count      float32
}

/* method to determine the value of a stock position */
func (s stockPosition) getValue() float32 {
    return s.sharePrice * s.count
}

type car struct {
    make  string
    model string
    price float32
}

/* method to determine the value of a car */
func (c car) getValue() float32 {
    return c.price
}

/* contract that defines different things that have value */
type valuable interface {
    getValue() float32
}

func showValue(asset valuable) {    //接着定义一个使用 valuable 类型作为参数的函数 showValue(),
    fmt.Printf("Value of the asset is %fn", asset.getValue())
}

func main() {    //所有实现了 valuable 接口的类型都可以用这个函数
    var o valuable = stockPosition{"GOOG", 577.20, 4}
    showValue(o)
    o = car{"BMW", "M3", 66500}
    showValue(o)
}

很屌,很流弊

总结:
多态 的 Go 版本,多态是面向对象编程中一个广为人知的概念:根据当前的类型选择正确的方法,或者说:同一种类型在不同的实例上似乎表现出不同的行为

  • go 的string()方法
package main

import (
    "fmt"
    "strconv"
)

type TwoInts struct {
    a int
    b int
}

func main() {
    two1 := new(TwoInts)
    two1.a = 12
    two1.b = 10
    fmt.Printf("two1 is: %vn", two1)
    fmt.Println("two1 is:", two1)
    fmt.Printf("two1 is: %Tn", two1)
    fmt.Printf("two1 is: %#vn", two1)
}
// 为Twolnts定义一个String()方法,以后输出就靠了它
func (tn *TwoInts) String() string {
    return "(" + strconv.Itoa(tn.a) + "/" + strconv.Itoa(tn.b) + ")"
}

输出
two1 is: (12/10)
two1 is: (12/10)
two1 is: *main.TwoInts
two1 is: &main.TwoInts{a:12, b:10}
  • go的测试文件

很简单

测试函数必须有这种形式的头部:

func TestAbcde(t *testing.T)
T 是传给测试函数的结构类型,用来管理测试状态,支持格式化测试日志,如 t.Log,t.Error,t.ErrorF 等。在函数的结尾把输出跟想要的结果对比,如果不等就打印一个错误。成功的测试则直接返回。

用下面这些函数来通知测试失败:

1)func (t *T) Fail()

    标记测试函数为失败,然后继续执行(剩下的测试)。
2)func (t *T) FailNow()

    标记测试函数为失败并中止执行;文件中别的测试也被略过,继续执行下一个文件。
3)func (t *T) Log(args ...interface{})

    args 被用默认的格式格式化并打印到错误日志中。
4)func (t *T) Fatal(args ...interface{})

    结合 先执行 3),然后执行 2)的效果。
运行 go test 来编译测试程序,并执行程序中所有的 TestZZZ 函数。如果所有的测试都通过会打印出 PASS。

gotest 可以接收一个或多个函数程序作为参数,并指定一些选项。

结合 --chatty 或 -v 选项,每个执行的测试函数以及测试状态会被打印。

例如:

go test fmt_test.go --chatty
=== RUN fmt.TestFlagParser
--- PASS: fmt.TestFlagParser
=== RUN fmt.TestArrayPrinter
--- PASS: fmt.TestArrayPrinter
...


还可以用作基准测试

测试代码中必须包含以 BenchmarkZzz 打头的函数并接收一个 *testing.B 类型的参数,比如:

func BenchmarkReverse(b *testing.B) {
    ...
}
命令 go test –test.bench=.* 会运行所有的基准测试函数;代码中的函数会被调用 N 次(N是非常大的数,如 N = 1000000),
并展示 N 的值和函数执行的平均时间,单位为 ns(纳秒,ns/op)。如果是用 testing.Benchmark 调用这些函数,直接运行程序即可。

up.go

package uc

import "strings"

func UpperCase(str string) string{
    return strings.ToUpper(str)
}

up_test.go这个名称需要注意,应该是##_test.go

package uc

import "testing"    //需要引用testing这个模块

type ucTest struct{
    in, out string
}

var ucTests = []ucTest{
    ucTest{"abc","ABC"},
    ucTest{"cvo-az","CVO-AZ"},
}

func TestUC(t *testing.T){    //这里使用了testing模块,注意名字以Test开头,也必须使用这样的函数头
    for _, ut := range ucTests{
        uc := UpperCase(ut.in)
        if uc != ut.out{
            t.Errorf("UpperCase(%s) = %s, must be %s", ut.in, uc, ut.out )
        }
    }

}

最后使用

go test

来进行测试

  • go中包的引用

go中的包想要被引用的话,最好将代码都放入gopath的src中,如果想引用某个包,需要先将这个包使用go install进行编译,(此时所有文件需要package 的包文件名相同,否则会编译出错)编译成.a文件,才能够被引用,如果两个.go文件都在同一个包中,则不能存在相同的函数,

import (
    "fmt"
    "golanglearn/pack1"
)

此时包pack1应该已经被编译,才能被引用

import . "./pack1"
//当使用.来做为包的别名时,你可以不通过包名来使用其中的项目。例如:test := ReturnStr()代替test := pack1.ReturnStr()
  • go中的锁
    锁和 sync 包来实现锁
    sync.Mutex 是一个互斥锁,它的作用是守护在临界区入口来确保同一时间只能有一个线程进入临界区。

假设 info 是一个需要上锁的放在共享内存中的变量。通过包含 Mutex 来实现的一个典型例子如下:

import  "sync"

type Info struct {
    mu sync.Mutex
    // ... other fields, e.g.: Str string
}

如果一个函数想要改变这个变量可以这样写:

func Update(info *Info) {
    info.mu.Lock()
    // critical section:
    info.Str = // new value
    // end critical section
    info.mu.Unlock()
}

还有一个很有用的例子是通过 Mutex 来实现一个可以上锁的共享缓冲器:

type SyncedBuffer struct {
    lock    sync.Mutex
    buffer  bytes.Buffer
}

在 sync 包中还有一个 RWMutex 锁:他能通过 RLock() 来允许同一时间多个线程对变量进行读操作,但是只能一个线程进行写操作。如果使用 Lock() 将和普通的 Mutex 作用相同。包中还有一个方便的 Once 类型变量的方法 once.Do(call),这个方法确保被调用函数只能被调用一次。

相对简单的情况下,通过使用 sync 包可以解决同一时间只能一个线程访问变量或 map 类型数据的问题。如果这种方式导致程序明显变慢或者引起其他问题,我们要重新思考来通过 goroutines 和 channels 来解决问题,这是在 Go 语言中所提倡用来实现并发的技术。

  • new() 与make()

new(T) 为每个新的类型T分配一片内存,初始化为 0 并且返回类型为*T的内存地址:这种方法 返回一个指向类型为 T,值为 0 的地址的指针,它适用于值类型如数组和结构体;它相当于 &T{}。

make(T) 返回一个类型为 T 的初始值,它只适用于3种内建的引用类型:切片、map 和 channel。

  • 结构体的标签

结构体中的字段除了有名字和类型外,还可以有一个可选的标签(tag):它是一个附属于字段的字符串,可以是文档或其他的重要标记。标签的内容不可以在一般的编程中使用,只有包 reflect 能获取它。它可以在运行时自省类型、属性和方法,比如:在一个变量上调用 reflect.TypeOf()可以获取变量的正确类型,如果变量是一个结构体类型,就可以通过 Field 来索引结构体的字段,然后就可以使用 Tag 属性。
标签的示例

type TagType struct { // tags
    field1 bool   "An important answer"
    field2 string "The name of the thing"
    field3 int    "How much there are"
}

应用

package main

import (
    "fmt"
    "reflect"
)

type TagType struct { // tags
    field1 bool   "An important answer"
    field2 string "The name of the thing"
    field3 int    "How much there are"
}

func main() {
    tt := TagType{true, "Barak Obama", 1}
    for i := 0; i < 3; i++ {
        refTag(tt, i)
    }
}

func refTag(tt TagType, ix int) {
    ttType := reflect.TypeOf(tt)     //在一个变量上调用 `reflect.TypeOf()`可以获取变量的正确类型,
    ixField := ttType.Field(ix)    // 如果变量是一个结构体类型,就可以通过 Field 来索引结构体的字段
    fmt.Printf("%vn", ixField.Tag)    //然后就可以使用 Tag 属性。
}




//answer
An important answer
The name of the thing
How much there are
  • 结构体工厂
    Go 语言不支持面向对象编程语言中那样的构造子方法,但是可以很容易的在 Go 中实现 “构造子工厂”方法。为了方便通常会为类型定义一个工厂,按惯例,工厂的名字以 new 或 New 开头。假设定义了如下的 File 结构体类型:
type File struct {
    fd      int     // 文件描述符
    name    string  // 文件名
}

下面是这个结构体类型对应的工厂方法,它返回一个指向结构体实例的指针:

func NewFile(fd int, name string) *File {
    if fd < 0 {
        return nil
    }

    return &File{fd, name}
}

然后这样调用它:

f := NewFile(10, "./test.txt")

性能和 UI:

  • GO-8031 — GoLand 会更快地显示方法的 ‘implemented’ icon,因为它在分析过程中处理的元素更少。
  • GO-8034 — 当点击实现界面的类型的 gutter 图标并且有很多方法时,UI 不再冻结。
  • GO-7952 — 当我们将现有变量用作字段值时,填充字段(Fill Fields)更有用。

图片 1

其他用例
type matrix struct {
    ...
}

func NewMatrix(params) *matrix {
    m := new(matrix) // 初始化 m
    return m
}

在其他包里使用工厂方法:

package main
import "matrix"
...
wrong := new(matrix.matrix)     // 编译失败(matrix 是私有的)
right := matrix.NewMatrix(...)  // 实例化 matrix 的唯一方式
  • go结构体声明与使用的三种方式
type Person struct{
    firstName string
    lastName string
}

func upPerson(p *Person){
    p.firstName = strings.ToUpper(p.firstName)
    p.lastName = strings.ToUpper(p.lastName)
}


  //usage
    var pers1 Person
    pers1.firstName = "Chris"
    pers1.lastName = "Woodward"
    upPerson(&pers1)
    fmt.Printf("The name of the person is %s %s n ",pers1.firstName,pers1.lastName)

    pers2 := new(Person)
    pers2.firstName = "yu"
    (*pers2).lastName = "zhipeng"    // this one is OK 
    upPerson(pers2)
    fmt.Printf("The name of the person is %s %s n", pers2.firstName,pers2.lastName)

    pers3 := &Person{"Chris","Woodward"}
    upPerson(pers3)
    fmt.Printf("The name of the person is %s %s n ",pers3.firstName,pers3.lastName)
  • go格式化字符串
    fmt.Println会直接输出所有的东西,不是格式化字符串,他只是平淡无奇的输出所有,还给你赠送一个换行
    fmt.Println("Hello mk %s",mk.str)
    fmt.Println("last ",intr)
>>>Hello mk %s zpyu
>>>last  {0 3}

fmt.Printf会格式化字符串,不赠送换行

    fmt.Printf("Hello mk %s",mk.str)
    fmt.Println("last ",intr)

>>>Hello mk zpyulast  {0 3}
  • 错误

Go 程序使用 error 值来表示错误状态。

与 fmt.Stringer 类似, error 类型是一个内建接口:

type error interface {
Error() string
}
只要是实现了Error这个方法,就是实现了这个接口
(与 fmt.Stringer 类似,fmt 包在输出时也会试图匹配 error。)

package main

import (
    "fmt"
    "time"
)

type MyError struct {
    When time.Time
    What string
}

func (e *MyError) Error() string {    //MyError实现了Error方法,就是实现了error的接口
    return fmt.Sprintf("at %v, %s",
        e.When, e.What)
}


func run() error {    //这里要求回复一个error的错误
    return &MyError{    //然后这里是回复了一个MyError,因为MyError实现了error这个接口,里面有Error方法。
        time.Now(),
        "it didn't work",
    }
}

func main() {
    if err := run(); err != nil {
        fmt.Println(err)
    }
}

接口实现方法

package main

import (
    "fmt"
    "math"
)

type Abser interface {
    Abs() float64
}

func main() {
    var a Abser
    f := MyFloat(-math.Sqrt2)
    v := Vertex{3, 4}

    a = f  // a MyFloat 实现了 Abser
    a = &v // a *Vertex 实现了 Abser

    // 下面一行,v 是一个 Vertex(而不是 *Vertex)
    // 所以没有实现 Abser。

    fmt.Println(a.Abs())
}

type MyFloat float64

func (f MyFloat) Abs() float64 {
    if f < 0 {
        return float64(-f)
    }
    return float64(f)
}

type Vertex struct {
    X, Y float64
}

func (v *Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

这里的实现原理:就是有一个接口,然后接口里定义了Abs()这个方法,不管谁继承我,只要是实现了这个Abs()方法,就算你实现了我这个接口。

    var a Abser
    f := MyFloat(-math.Sqrt2)
    v := Vertex{3, 4}

    a = f  // a MyFloat 实现了 Abser
    a = &v // a *Vertex 实现了 Abser

这里的话,就是结构体来实现了接口,需要注意的是,他们实现的时候给的值,一个是指针 一个是值,那是因为他们在定义的时候就是不同的,类型通过实现那些方法来实现接口。 没有显式声明的必要;所以也就没有关键字“implements“。隐式接口解藕了实现接口的包和定义接口的包:互不依赖。

func (v *Vertex) Abs() float64 {

func (f MyFloat) Abs() float64 {

一个定义的时候就是指针,引用的时候也要是指针才行

  • 另外一个接口实例

重构

  • GO-8065, GO-8068 — Extract Interface 会遵循现有的声明,如果未在新创建的界面中使用,也不会废弃未导出的接收器类型。
  • GO-7982 — Change Signature 会在测试中处理包前缀。

支持使用 Mozilla rr 进行远程调试

在 2019.3 版本中,我们可以使用 Mozilla rr 远程调试应用程序。大致步骤如下:

  1. 在远程机器上获取 rr 跟踪
  2. 在远程机器上启动调试器,如下所示:
    dlv --headless --api-version 2 -l localhost:2345 replay /path/to/trace/dir /path/to/binary
  3. 从 IDE 连接到此机器

Stringers

一个普遍存在的接口是 fmt 包中定义的 Stringer

type Stringer interface {
    String() string
}

Stringer 是一个可以用字符串描述自己的类型。fmt包 (还有许多其他包)使用这个来进行输出。

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func (p Person) String() string {
    return fmt.Sprintf("%v (%v years)", p.Name, p.Age)
}

func main() {
    a := Person{"Arthur Dent", 42}
    z := Person{"Zaphod Beeblebrox", 9001}
    fmt.Println(a, z)
}

注意这里Person实现的方法是String(),所以算是实现了Stringer接口的String()方法,也就是实现了这个接口喽。


方法
Go 没有类。然而,仍然可以在结构体类型上定义方法。

方法接收者 出现在 func 关键字和方法名之间的参数中。

type MyFloat float64

func (f MyFloat) Abs() float64 {
    if f < 0 {
        return float64(-f)
    }
    return float64(f)
}

方法的接受者也就是 MyFloat


map 必须用make 来创建

func main() {
    m := make(map[string]int)
    m["Bell Labs"] = 1
    fmt.Println(m["Bell Labs"])
}

m := make(map[string]int)
键是字符串 值是整数


代码格式化

代码格式功能获得了许多修复和改进:

  • GO-7431 — Reformat Code 与 go fmt 的工作方式更相似。

GoLand 现在会正确地对齐字段声明、参数列表、块语句、case 子句、const 块和多行复合字面量后面的注释等。另外,GoLand 会在多值返回中的结构初始值设定项中放置适当的缩进、在 switch-case 语句中划分特定的块、在注释后的 var/const 值、多行表达式内的注释以及具有多行条件语句的 if 之后等等。

有关代码格式化功能的错误修复完整列表,请点此参阅。

性能

此版本修复了一些问题,使得 GoLand 的运行速度更快,CPU 消耗更少。

range

for 循环的 range 格式可以对 slice 或者 map 进行迭代循环

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}

    for i, v := range pow  {
        fmt.Printf("2**%d = %dn", i, v)
    }

调试器

调试器也修复了一些错误:

  • GO-7770 — 函数调用可在 Evaluate Expression 窗口和 log breakpoint 属性中工作。
  • GO-7060 — 调试器会在代码编辑器中显示变量的正确位置。

重构

“Change Signature”功能会在“Parameters”和“Result parameters”选项卡中显示参数类型。我们还可以通过勾选新的“Reuse types”选择框以折叠“Signature Preview”中的结果类型。

图片 2

此外,还增加了一个新的意图动作 —— Reuse signature types(复用签名类型),它可将参数定义合并到一个声明中(Alt + Enter)。

最后,提取变量(Extract Variable)和重命名(Rename)功能在名字方面会提供更好的建议。例如输入err会建议使用用于表达式类型的 error,输入ctx则会建议使用context.Context

图片 3

Slice

一个 slice 会指向一个序列的值,并且包含了长度信息。

[]T 是一个元素类型为 T 的 slice。

len(s) 返回 slice s 的长度。

slice里 面可以包含各种类型,包括slice 里面进行赋值的时候要用{ },注意不是( )

    s := []int{2, 3, 5, 7, 11, 13}
    for i := 0; i < len(s); i++ {
        fmt.Printf("s[%d] == %dn", i, s[i])
    }

    game := [][]string{
        []string{"_", "_", "_"},
        []string{"_", "_", "_"},
        []string{"_", "_", "_"},
    }
game[0][0] = "X"
game[0][1] = "Y"


func printBoard(s [][]string) {
    for i := 0; i < len(s); i++ {
        fmt.Printf("%sn", strings.Join(s[i], "  "))
    }
}

查看strings Join 方法

go doc strings Join

slice可以被切片
s[lo:hi]

构造slice
slice 由函数 make 创建。这会分配一个全是零值的数组并且返回一个 slice 指向这个数组:

a := make([]int, 5) // len(a)=5

为了指定容量,可传递第三个参数到 make:

b := make([]int, 0, 5) // len(b)=0, cap(b)=5

b = b[:cap(b)] // len(b)=5, cap(b)=5
b = b[1:]      // len(b)=4, cap(b)=4

添加元素 append

    var a []int
    printSlice("a", a)

    // append works on nil slices.
    a = append(a, 0)
    printSlice("a", a)

常规功能

  • GO-7708 — 从 IDE 安装 Go SDK 会按预期运行,并没有任何异常

此次更新的错误修复完整列表请查看这里。

(文/开源中国)    

其他改进

  • 在该版本中,我们可以在 Hierarchy 工具窗口分析被调用者方法的调用树。在此前的版本中,只支持分析调用者方法的调用树。现在新增了两个专用按钮,可方便地在调用者和被调用者之间切换。此外,还可以通过点击菜单中的特殊按钮对调用树中的元素进行排序。

图片 4

  • 检查 Bool 条件代码(声明冗余检查的一部分)不会再警告使用 const booleans。
  • Go Module 包的名称在 Project View 中以更清晰、更简单的方式呈现。

图片 5

对了,参与使用 EAP 并进行积极反馈还有机会获得 GoLand 的一年免费订阅和品牌T恤。

>>>EAP 版本下载地址:https://www.jetbrains.com/go/nextversion

图片 6

(文/开源中国)    

数组

类型 [n]T 是一个有 n 个类型为 T 的值的数组。

表达式

var a [10]int

定义变量 a 是一个有十个整数的数组。

package main

import "fmt"

func main() {
    var a [2]string
    var b [2]int
    a[0] = "Hello"
    a[1] = "World"
    b[0] = 0
    b[1] = 1
    fmt.Println(a[0], a[1]) //Hello World
    fmt.Println(a)  // [Hello World]
    fmt.Println(b[0])    //0
    fmt.Println(b[1])    //1
    fmt.Println(b)    //[0 1]
}

结构体

结构体字段可以通过结构体指针来访问。

通过指针间接的访问是透明的。

package main

import "fmt"

type Vertex struct {
    X int
    Y int
}

func main() {
    v := Vertex{1, 2} 
    p := &v
    fmt.Println(v)    //{1 2}
    fmt.Println(p)   //&{1 2}
    fmt.Println(p.X)   //1
    fmt.Println(v.X)   //1
    p.X = 1e5
    fmt.Println(v)   //{100000 2}
}

指针

func main() {
    i, j := 42, 2701

    p := &i         // point to i  把i的地址取出来给p
    fmt.Println(*p) //42  p通过*p指到地址对应的值
    *p = 21         // set i through the pointer
    fmt.Println(*p)  //21
    i = 1
    fmt.Println(i) // 1
    *p = 2   //值被覆盖 也就是间接引用覆盖
    fmt.Println(i)  // 2

    p = &j         // point to j  地址赋值
    *p = *p / 37   // divide j through the pointer 应用
    fmt.Println(j) // 73
}

没有条件的 switch
没有条件的 switch 同 switch true 一样。
这一构造使得可以用更清晰的形式来编写长的 if-then-else 链。

    switch {
    case t.Hour() < 12:
        fmt.Println("Good morning!")
    case t.Hour() < 17:
        fmt.Println("Good afternoon.")
    default:
        fmt.Println("Good evening.")
    }

go build 加上可以编译的go源文件可以得到一个可执行文件。
go install 在编译源代码之后还安装到指定的目录
go get 从指定源上面下载或者更新指定的代码和依赖,并对他们进行编译和安装
go get = git clone + go install

go语言学习笔记(学自菜鸟教程)

特色

  • 特色

简洁、快速、安全

并行、有趣、开源

内存管理、v数组安全、编译迅速

  • 应用
    应用于搭载 Web 服务器,存储集群或类似用途的巨型中央服务器的系统编程语言。
    对于高性能分布式系统领域而言,Go语言无疑比大多数其它语言有着更高的开发效率。它提供了海量并行的支持

go语言基础组成部分

  • 包声明
    package main表示一个可独立执行的程序,每个 Go 应用程序都包含一个名为 main 的包。这个和python的main是大同小异的
  • 引入包 对应于python中的import
  • 函数
  • 变量
  • 语句 & 表达式
  • 注释
package main     //包名

import "fmt"    //引入包

func  main()   //程序开始执行的函数
{
    fmt.Println("hello world!")    //输出到控制台
}

包中对象的类型

  • 像面向对象语言中的 public
    当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:Group1,那么使用这种形式的标识符的对象可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出

  • 像面向对象语言中的 protected
    标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的

标识符

标识符用来命名变量、类型等程序实体。一个标识符实际上就是一个或是多个字母(AZ和az)数字(0~9)、下划线_组成的序列,但是第一个字符必须是字母或下划线而不能是数字。

分隔符与注释 变量声明

  • 分隔符
    一行代表一个语句结束

如果多个语句在一行可以用;分隔(不鼓励)

  • 注释
//单行注释
/*多行注释*/
  • 声明
    声明必须用空格分来

var age int;

变量与运算符加空格

变量声明

变量声明
  • 指定变量类型,声明后若不赋值,使用默认值。

var v_name v_type
v_name = value

  • 根据值自行判定变量类型。

var v_name = value

  • 省略var, 注意 :=左侧的变量不应该是已经声明过的,否则会导致编译错误。

v_name := value

// 例如
var a int = 10
var b = 10
c : = 10
函数体内(使用 := 赋值操作符) 初始化声明
  • 只能用在函数体内
  • 如果在相同的代码块中,我们不可以再次对于相同名称的变量使用初始化声明
  • 声明了一个局部变量却没有在相同的代码块中使用它,同样会得到编译错误
func main() {
    var w string = "I am w"
    e, r := 1, "I am r"
    println(x, y, a, b, c, d, e, f, g, h, w, e, r)

}
全局变量

但是全局变量是允许声明但不使用。 同一类型的多个变量可以声明在同一行,如:

var a, b, c int

多变量可以在同一行进行赋值,如:

a, b, c = 5, 7, "abc"

上面这行假设了变量 a,b 和 c 都已经被声明,否则的话应该这样使用:

a, b, c := 5, 7, "abc"

右边的这些值以相同的顺序赋值给左边的变量,所以 a 的值是 5, b 的值是 7,c 的值是 "abc"。
这被称为 并行 或 同时 赋值。
如果你想要交换两个变量的值,则可以简单地使用 a, b = b, a。

语言常量(布尔,数字,字符串)

  • 定义格式

显式声明

const b string = 'abdc'

隐式声明

const b = 'abc'

多个相同类型可以简写

const c1, c2 = v1, v2

  • iota
    在每一个const关键字出现时,被重置为0,然后再下一个const出现之前,每出现一次iota,其所代表的数字会自动增加1。
package main

import "fmt"

func main(){
    const(
            a = iota
            b
            c
            d = "he"
            e
            f
            g
            h = iota
            i)
    fmt.Println(a, b, c, d, e, f, g, h, i)


}

输出0 1 2 he he he he 7 8

Go语言运算

与python的运算符类似

  • 逻辑运算符

&& 表示AND
|| 表示OR
! 表示 False

  • 位运算符
    & 参与运算的两数各对应的二进位相与。

| 功能是参与运算的两数各对应的二进位相或

^ 与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。

<< 左移n位就是乘以2的n次方。 其功能把"<<"左边的运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补0。

其功能是把">>"左边的运算数的各二进位全部右移若干位,">>"右边的数指定移动的位数。

赋值运算符

=

+=   相加后赋值

-=    

*=    相乘后赋值

/=    相除后赋值

%=    求余后赋值

<<=    左移后赋值

/ >>=    右移后赋值

&=    按位与后赋值

^=    按位异或后赋值

|=    按位或后赋值


* 其他

& 返回变量存储地址
*  指针变量

条件语句与循环语句

  • 条件语句

if语句

if else语句

switch语句 switch 语句用于基于不同条件执行不同动作。

select语句 select 语句类似于 switch
语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。

  • 循环语句

for 循环

  package main

  import "fmt"


  func main(){
          for true {
          fmt.Println("this is a circle")
      }
  }
  • 循环控制语句
    break

continue

goto

函数

func function_name( [parameter list] ) [return_types] {
   函数体
}

各部分说明

parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。

return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。

  • 函数参数

值传递与引用传递

值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参

引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

默认使用值传递,想要使用引用传递的话,就要使用到指针,比如

/* 定义交换值函数*/
func swap(x *int, y *int) {
   var temp int
   temp = *x    /* 保持 x 地址上的值 */
   *x = *y      /* 将 y 值赋给 x */
   *y = temp    /* 将 temp 值赋给 y */
}

这里使用到了指针

  • Go 语言函数作为值
 func main(){
   /* 声明函数变量 */
   getSquareRoot := func(x float64) float64 {
      return math.Sqrt(x)
   }
   /* 使用函数 */
   fmt.Println(getSquareRoot(9))
}
  • 函数闭包(匿名函数的优越性在于可以直接使用函数内的变量,不必申明。)
在实例中,我们创建了函数 getSequence() ,返回另外一个函数。该函数的目的是在闭包中递增 i 变量,代码如下:

package main

import "fmt"

func getSequence() func() int {
   i:=0
   return func() int {
      i+=1
     return i  
   }
}

函数方法


Go语言数组

声明

var variable_name [SIZE] variable_type

以上为一维数组的定义方式。数组长度必须是整数且大于 0。例如以下定义了数组 balance 长度为 10 类型为 float32:

var balance [10] float32

初始化数组

初始化数组中 {} 中的元素个数不能大于 [] 中的数字

var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

如果忽略 [] 中的数字不设置数组大小,Go 语言会根据元素的个数来设置数组的大小:

var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

访问数组元素
格式为数组名后加中括号,中括号中为索引的值。例如:

float32 salary = balance[9]

go语言指针

一个指针变量可以指向任何一个值的内存地址, 它指向那个值的内存地址。格式化时使用

声明

var var_name *var-type

var ip *int 
var fp *float32 

使用

  • 定义指针变量。
  • 为指针变量赋值。
  • 访问指针变量中指向地址的值。

空指针

一个指针变量通常缩写为 ptr。

当一个指针被定义后没有分配到任何变量时,它的值为 nil。

go语言结构体(感觉很像xml)

Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型。

结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。

结构体表示一项记录,比如保存图书馆的书籍记录,每本书有以下属性:

Title :标题
Author : 作者
Subject:学科
ID:书籍ID

结构体定义需要使用 type 和 struct 语句。struct 语句定义一个新的数据类型,结构体有中一个或多个成员。type 语句设定了结构体的名称。结构体的格式如下:

type struct_variable_type struct {
   member definition;
   member definition;
   ...
   member definition;
}

一旦定义了结构体类型,它就能用于变量的声明,语法格式如下:

variable_name := structure_variable_type {value1, value2...valuen}

package main

import "fmt"

  type Book struct{
    title string
    author string
  }
func main() {
    var Book1 Book
    Book1.title = "love of the time of huolen"
    Book1.author = "Gaxime"

    var Book2 Book
    Book2.title = "Harry Potter"
    Book2.author = "J.K Rooly"

//     fmt.Printf("Book1的书名是%sn", Book1.title)
//     fmt.Printf("Book1的作者是%sn", Book1.author)
    print(&Book1)
    print(&Book2)
}

func print(book *Book){
  fmt.Printf("Book 的书名是%sn", book.title)
  fmt.Printf("Book 的作者是%snn", book.author)

}

go语言切片 格式化时为%v

定义 Go 数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片("动态数组"),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。

var identifier []type

切片不需要说明长度或者通过make()来创建切片

var slice1 []type = make([]type, len)

slice1 := make([]type, len)

make([]T, length, capacity) #capacity容量的意思


切片的初始化

s := [] int{1,2,3 }

[]表示的是切片,{1,2,3} 表示初始值

初始化切片s,是数组arr的引用

s := arr[:]

将arr中从下标startIndex到endindex-1下的元素创建一个新的切片

s := arr[startIndex:endIndex]

make函数来初始化切片s,[]int标识其元素类型为int的切片

s := make([]int, len, cap)

  • len()与cap()

切片是可索引的,并且可以由 len() 方法获取长度。

切片提供了计算容量的方法 cap() 可以测量切片最长可以达到多少。

切片截取

numbers := []int{0,1,2,3,4,5,6,7,8}

numbers[4:]
  • append() 和 copy()函数

    如果想增加切片的容量,我们必须创建一个新的更大的切片并把原分片的内容都拷贝过来。

package main

import "fmt"

func main() {
  numbers := []int{1,2,3,3,4,5}
  pslice(numbers)  
  numbers = append(numbers,2)
  pslice(numbers)
  number1 := make([]int, len(numbers)*2, cap(numbers)*2)
  copy(number1,numbers)
  pslice(number1)
  number1 = append(number1,21)
  pslice(number1)
}

func pslice(x []int){
  fmt.Printf("%d,%d,%vn",len(x),cap(x),x)
}

Go中的语言范围(range)

Go 语言中 range 关键字用于for循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。在数组和切片中它返回元素的索引值,在集合中返回 key-value 对的 key 值

package main

import "fmt"

func main(){
    nums := []int{2,3,4}
    sum := 0
    for index, num := range nums{
        sum += num
        fmt.Println("index is ",index)
        fmt.Println("num is ",num)
    }
    fmt.Println("sum:",sum)

    kvs := map[string]string{"a":"apple","b":"banana"}
    for k, v := range kvs{
        fmt.Printf("%s==>%sn",k,v)
    }

    for i, v := range "12go"{
        fmt.Println(i, v)
    }


}

GO语言Map(集合)

  • 定义:
/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type

/* 使用 make 函数 */
map_variable := make(map[key_data_type]value_data_type)

必须使用make声明map,才能存储键值对

package main

import "fmt"

func main(){
  var countryMap map[string]string
  countryMap = make(map[string]string)
  countryMap["France"] = "Paris"
  countryMap["China"] = "Beijing"
  for country := range countryMap {
      fmt.Println("Capital of",country,"is",countryMap[country])
   }

}
  • delete()函数
package main

import "fmt"

func main(){
    countrycapMap := map[string]string{"F":"P","I":"R"}
    fmt.Println("原始map")
    for country := range countrycapMap{
        fmt.Println("Capital of ",country,"is",countrycapMap[country])
    }


    fmt.Println("删除后的map")
    delete(countrycapMap,"F")
    for country := range countrycapMap{
        fmt.Println("Capital of ",country,"is",countrycapMap[country])
    }
}

递归

package main

import "fmt"

func fibona(n int) int{
  if n < 2{
    return n
  }

  return fibona(n - 2) + fibona(n-1)

}

func main(){
  var i int
  for i = 0; i < 10; i++{
    fmt.Printf("%dtn",fibona(i))
  }
}

类型转换

将整型转化为浮点型

func main() {
   var sum int = 17
   var count int = 5
   var mean float32

   mean = float32(sum)/float32(count)
   fmt.Printf("mean 的值为: %fn",mean)
}

接口

Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。

/* 定义接口 */
type interface_name interface {
   method_name1 [return_type]
   method_name2 [return_type]
   method_name3 [return_type]
   ...
   method_namen [return_type]
}

/* 定义结构体 */
type struct_name struct {
   /* variables */
}

/* 实现接口方法 */
func (struct_name_variable struct_name) method_name1() [return_type] {
   /* 方法实现 */
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
   /* 方法实现*/
}

调用

package main

import "fmt"


//定义接口  里面说明包含的方法
type Phone interface{
  call()
}

//定义结构体
type NokiaPhone struct{

}

//实现接口方法
func (nokiaPhone NokiaPhone) call() {
    fmt.Println(" I am NokiaPhone, I can call you ")  
}

//调用
func  main() {
  var phone Phone
  phone = new(NokiaPhone)
  phone.call()

}

Go错误处理

Go 语言通过内置的错误接口提供了非常简单的错误处理机制。
error类型是一个接口类型,这是它的定义:

type error interface {
    Error() string
}

本文由威尼斯手机平台发布于项目,转载请注明出处:具体如下,bug、解决小故障、修复可用性以及性能方面的问题

上一篇:【威尼斯电子平台】详细的情况见发表表达,3.6以致在科学计算和多少深入分析中常用的Python模块 下一篇:没有了
猜你喜欢
热门排行
精彩图文