Go+ 概述 | 带你用一文全面了解 Go+

Go+ 2021-11-19 11:28:29
加精

目录

一、Go+ 是什么

二、Go+ 特点:“三位一体”

三、Go+ 优势

四、如何安装 Go+

五、Go+ 代码规范(重要)

六、关于 Go+ 的特性概要

七、Go+ 相关教程

八、Playground

九、与 Go 的兼容性

十、字节码与 Go 代码

十一、Go+ 特性

十二、 IDE 插件

十三、贡献

十四、拓展资料


一、Go+ 是什么

Go+ 是七牛云 CEO 许式伟发明的一门可用于工程、STEM 教育和数据科学的编程语言,于 2020 年 7 月正式发布,2021 年 10 月推出 1.0 版本。

 

二、Go+ 特点:“三位一体”

Go+ Slogan:“The Go+ language for engineering, STEM education, and data science”

Go+ 是目前第一个顺应“三位一体”发展潮流的编程语言,同时兼顾工程、STEM 教育、数据科学三大领域:

  • for engineering:致力于让工程师可以使用简洁、容易掌握的语言去工作,这在纷繁复杂的工程技术领域是非常重要的进化;
  • for STEM education:Go+ 简单易学,非常适合作为青少年学习编程的入门语言,且能在未来的工作中的延续使用,无需切换语言;
  • for data science:目标是让工程师和数据科学家可以用相同的语言去对话,这在以数据驱动创新的未来尤为重要。

 

三、Go+ 优势

Go+ 有三大优势:更简单,更强大,兼容性强。其中:

  • 语法更加简单、优雅。在继承 Go 语言特性最小化的优势和工程理念的基础上,Go+ 更接近自然语言,有理数更贴近数学的表达方式;
  • 低代码化,去复杂性。入门门槛较低,入门使用时屏蔽了工程化的复杂性;
  • 性能强大。强化每行代码的能力,完成功能所需的代码量更少;

 

对于「三位一体」面向的三个领域,Go+ 也有着自身的优势:

1. 工程用:

  • 将支持所有 Go 功能(包括部分支持cgo)。
  • Go+ 提供了更简单优雅的语法,比 Go 更接近自然语言。
  • Go+ 易于学习。您不必在一开始就处理工程的复杂性。
  • Go+ 赋能每一行代码。你可以用更少的代码做更多的工作。

 

2. STEM教育:

  • 与 Scratch 相比:Scratch 仅用于编程教学。它基于块状界面,自然直观,但与实际工程体验不一致。
  • 借鉴Code Monkey的经验,Go+ 直接使用代码进行编程教学,引入了低学习难度(不高于基于块的编程)和平滑的学习曲线。
  • Go+创新地实现了工程与教学的融合。你学习的语言也是你工作的语言。通过创建更有成效的课程,学生将获得更大的学习成就感。

 

3. 对于科学数据:

  • Go+ 提供了更强大的数学表达式功能,例如有理数表达式,可简化数据科学目的的编程。
  • Go+ 支持字节码后端和 Go 代码生成。
  • 与 Python 相比,Go+ 提供:
    • 更好的性能
    • 更像自然语言的语法
    • 与 Python 生态系统的兼容性(未来)
    • 数据科学和工程的相同语言

Go+ 已实现对 Go、Scratch,未来将兼容 Python。

 

四、如何安装 Go+

目前,我们建议您通过源码安装 Go+。

git clone https://github.com/goplus/gop.git
cd gop
# On mac/linux run:
./all.bash
# On Windows run:
all.bat

实际上, all.bash 和 all.bat 内部都会执行 go run cmd/install.go

 

五、Go+ 代码规范(重要)

 

六、关于 Go+ 的特性概要

关于 Go+ 的主要印象是什么?

  • 一种静态类型语言。
  • 完全兼容 Go 语言 。
  • 类似脚本语言的风格,代码比 Go 更易读。

例如,以下是合法的 Go+ 源代码:

println [1, 2, 3.4]

我们如何在 Go 语言中做到这一点?

package main


import "fmt"


func main() {
    fmt.Println([]float64{1, 2, 3.4})
}

当然,我们不仅仅做少打字的事情。

例如,我们支持 列表推导 ,这使得数据处理更容易。

println [x*x for x <- 1:6:2] // output: [1 9 25]

mapData := {"Hi": 1, "Hello": 2, "Go+": 3}
reversedMap := {v: k for k, v <- mapData}
println reversedMap // output: map[1:Hi 2:Hello 3:Go+]

我们会保持 Go+ 的简单性。这就是为什么我们称它为 Go+,而不是 Go++。

少即是指数级的多。

Go 是如此,Go+ 亦是如此。

 

七、Go+ 相关教程

 

八、Playground

基于 Docker 的 Go+ Playground(推荐):

基于 GopherJS 的 Go+ Playground(目前仅在 v0.7.x 中可用):

 

九、与 Go 的兼容性

将支持所有 Go 特性(包括部分支持 cgo ,见 下文 )。

所有 Go 包(即便这些软件包使用 cgo )都可以由 Go+ 导入。

import (
    "fmt"
    "strings"
)


x := strings.NewReplacer("?", "!").Replace("hello, world???")
fmt.Println "x:", x

并且所有 Go+ 包也可以导入到 Go 程序中。您需要做的只是使用 gop 命令而不是 go 。

首先,让我们创建一个名为 14-Using-goplus-in-Go 的目录。

然后在里面编写一个名为 foo 的 Go+ 包:

package foo


func ReverseMap(m map[string]int) map[int]string {
    return {v: k for k, v <- m}
}

然后在 Go 包 14-Using-goplus-in-Go/gomain 中使用它:

package main


import (
    "fmt"


    "github.com/goplus/tutorial/14-Using-goplus-in-Go/foo"
)


func main() {
    rmap := foo.ReverseMap(map[string]int{"Hi": 1, "Hello": 2})
    fmt.Println(rmap)
}

如何构建这个例子?您可以使用:

gop install -v ./...

访问 github.com/goplus/tutorial/14-Using-goplus-in-Go 来获取源代码。

 

十、字节码与 Go 代码

Go+ 支持字节码后端和 Go 代码生成。

当我们使用 gop 命令时,它会生成 Go 代码,将 Go+ 包转换为 Go 包。

gop run     # Run a Go+ program
gop install # Build Go+ files and install target to GOBIN
gop build   # Build Go+ files
gop test    # Test Go+ packages
gop fmt     # Format Go+ packages
gop clean   # Clean all Go+ auto generated files
gop go      # Convert Go+ packages into Go packages

当我们使用 igop 命令时,它会执行生成的的字节码。

igop  # Run a Go+ program

在字节码模式下,Go+ 不支持 cgo 。但是,在 Go 代码生成模式下,Go+ 完全支持 cgo 。

 

十一、Go+ 特性

1)有理数:bigint、bigrat、bigfloat

我们将有理数作为原生 Go+ 类型引入。我们使用后缀 r 来表示有理文字。例如, (1r << 200) 表示一个 big int ,其值等于 2 200 。 4/5r 表示有理常数 4/5。

var a bigint = 1r << 65 // bigint, large than int64

var b bigrat = 4/5r // bigrat

c := b - 1/3r + 3 * 1/2r // bigrat

println a, b, c



var x *big.Int = 1r << 65 // (1r << 65) is untyped bigint, and can be assigned to *big.Int

var y *big.Rat = 4/5r

println x, y

2)映射字面量

x := {"Hello": 1, "xsw": 3.4} // map[string]float64

y := {"Hello": 1, "xsw": "Go+"} // map[string]interface{}

z := {"Hello": 1, "xsw": 3} // map[string]int

empty := {} // map[string]interface{}

3)切片字面量

x := [1, 3.4] // []float64

y := [1] // []int

z := [1+2i, "xsw"] // []interface{}

a := [1, 3.4, 3+4i] // []complex128

b := [5+6i] // []complex128

c := ["xsw", 3] // []interface{}

empty := [] // []interface{}

4)Lambda 表达式

func plot(fn func(x float64) float64) {

// ...

}



func plot2(fn func(x float64) (float64, float64)) {

// ...

}



plot x => x * x // plot(func(x float64) float64 { return x * x })

plot2 x => (x * x, x + x) // plot2(func(x float64) (float64, float64) { return x * x, x + x })

 

5)推导结构类型

type Config struct {

Dir string

Level int

}



func foo(conf *Config) {

// ...

}



foo {Dir: "/foo/bar", Level: 1}

这里 foo {Dir: "/foo/bar", Level: 1} 等价于 foo (&Config {Dir: "/foo/bar", Level: 1}) 。但是,您不能将 foo (&Config {"/foo/bar", 1}) 替换为 foo {"/foo/bar", 1} ,因为将 {"/foo/bar", 1} 视为结构字面量会让人摸不着头脑。

您还可以在 return 语句中省略结构类型。例如:

type Result struct {

Text string

}



func foo() *Result {

return {Text: "Hi, Go+"} // return &Result{Text: "Hi, Go+"}

}

 

6)列表推导

a := [x*x for x <- [1, 3, 5, 7, 11]]

b := [x*x for x <- [1, 3, 5, 7, 11], x > 3]

c := [i+v for i, v <- [1, 3, 5, 7, 11], i%2 == 1]

d := [k+","+s for k, s <- {"Hello": "xsw", "Hi": "Go+"}]



arr := [1, 2, 3, 4, 5, 6]

e := [[a, b] for a <- arr, a < b for b <- arr, b > 2]



x := {x: i for i, x <- [1, 3, 5, 7, 11]}

y := {x: i for i, x <- [1, 3, 5, 7, 11], i%2 == 1}

z := {v: k for k, v <- {1: "Hello", 3: "Hi", 5: "xsw", 7: "Go+"}, k > 3}

 

7)从集合中选择数据

type student struct {

name string

score int

}



students := [student{"Ken", 90}, student{"Jason", 80}, student{"Lily", 85}]



unknownScore, ok := {x.score for x <- students, x.name == "Unknown"}

jasonScore := {x.score for x <- students, x.name == "Jason"}



println unknownScore, ok // output: 0 false

println jasonScore // output: 80

 

8)检查数据是否存在于集合中

type student struct {

name string

score int

}



students := [student{"Ken", 90}, student{"Jason", 80}, student{"Lily", 85}]



hasJason := {for x <- students, x.name == "Jason"} // is any student named Jason?

hasFailed := {for x <- students, x.score < 60} // is any student failed?

 

9)For 循环

sum := 0
for x <- [1, 3, 5, 7, 11, 13, 17], x > 3 {
    sum += x
}

10)Range 表达式( start:end:step )

for i <- :10 {
    println i
}

for i := range :10:2 {
    println i
}

for i := range 1:10:3 {
    println i
}

for range :10 {
    println "Range expression"
}

11)For range of UDT

type Foo struct {
}

// Gop_Enum(proc func(val ValType)) or:
// Gop_Enum(proc func(key KeyType, val ValType))
func (p *Foo) Gop_Enum(proc func(key int, val string)) {
    // ...
}

foo := &Foo{}
for k, v := range foo {
    println k, v
}

for k, v <- foo {
    println k, v
}

println {v: k for k, v <- foo}

注意:对于 udt.Gop_Enum(回调)的范围,无法使用 break/continue 或 return 语句。

 

12)For range of UDT2

type FooIter struct {
}

// (Iterator) Next() (val ValType, ok bool) or:
// (Iterator) Next() (key KeyType, val ValType, ok bool)
func (p *FooIter) Next() (key int, val string, ok bool) {
    // ...
}

type Foo struct {
}

// Gop_Enum() Iterator
func (p *Foo) Gop_Enum() *FooIter {
    // ...
}

foo := &Foo{}
for k, v := range foo {
    println k, v
}

for k, v <- foo {
    println k, v
}

println {v: k for k, v <- foo}

13)重载运算符

import "math/big"

type MyBigInt struct {
    *big.Int
}

func Int(v *big.Int) MyBigInt {
    return MyBigInt{v}
}

func (a MyBigInt) + (b MyBigInt) MyBigInt { // binary operator
    return MyBigInt{new(big.Int).Add(a.Int, b.Int)}
}

func (a MyBigInt) += (b MyBigInt) {
    a.Int.Add(a.Int, b.Int)
}

func -(a MyBigInt) MyBigInt { // unary operator
    return MyBigInt{new(big.Int).Neg(a.Int)}
}

a := Int(1r)
a += Int(2r)
println a + Int(3r)
println -a

14)错误处理

我们在 Go+ 中重新发明了错误处理规范。我们称之为 ErrWrap expressions :

expr! // panic if err
expr? // return if err
expr?:defval // use defval if err

如何使用它们?以下是一个例子:

import (
    "strconv"
)

func add(x, y string) (int, error) {
    return strconv.Atoi(x)? + strconv.Atoi(y)?, nil
}

func addSafe(x, y string) int {
    return strconv.Atoi(x)?:0 + strconv.Atoi(y)?:0
}

println `add("100", "23"):`, add("100", "23")!

sum, err := add("10", "abc")
println `add("10", "abc"):`, sum, err

println `addSafe("10", "abc"):`, addSafe("10", "abc")

这个例子的输出是:

add("100", "23"): 123
add("10", "abc"): 0 strconv.Atoi: parsing "abc": invalid syntax

===> errors stack:
main.add("10", "abc")
    /Users/xsw/tutorial/15-ErrWrap/err_wrap.gop:6 strconv.Atoi(y)?

addSafe("10", "abc"): 10

与相应的 Go 代码相比,它更清晰、更具可读性。

最有趣的是,返回错误包含完整的错误堆栈。当我们遇到错误时,很容易定位根本原因是什么。

这些 ErrWrap expressions 如何工作的?有关更多信息,请参阅 错误处理。

 

15)Auto property

让我们看一个用 Go+ 编写的例子:

import "gop/ast/goptest"

doc := goptest.New(`... Go+ code ...`)!

println doc.Any().FuncDecl().Name()

在许多语言中,有一个名为 property 的概念,它具有 get 和 set 方法。

假设我们有 get property ,上面的例子将是:

import "gop/ast/goptest"

doc := goptest.New(`... Go+ code ...`)!

println doc.any.funcDecl.name

在 Go+ 中,我们引入了一个名为 auto property 的概念。它是一个 get property ,但会自动实现。如果我们有一个名为 Bar() 的方法,那么我们将同时拥有一个名为 bar 的 get property 。

 

16)Unix shebang

您现在可以将 Go+ 程序用作 shell 脚本。例如:

#!/usr/bin/env -S gop run

println "Hello, Go+"

println 1r << 129
println 1/3r + 2/7r*2

arr := [1, 3, 5, 7, 11, 13, 17, 19]
println arr
println [x*x for x <- arr, x > 3]

m := {"Hi": 1, "Go+": 2}
println m
println {v: k for k, v <- m}
println [k for k, _ <- m]
println [v for v <- m]

访问 20-Unix-Shebang/shebang 来获取源代码。

 

17)Go 特性

将支持所有 Go 特性(包括部分支持 cgo)。在字节码模式下,Go+ 不支持 cgo 。然而,在 Go 代码生成模式下,Go+ 完全支持 cgo 。

 

十二、 IDE 插件

 

十三、贡献

Go+ 项目欢迎所有贡献者。我们感谢您的帮助!

这是 Go+ 贡献者列表 。我们为每位贡献者颁发一个电子邮件帐户 (XXX@goplus.org)。 我们建议您使用此电子邮件帐户提交代码:

git config --global user.email XXX@goplus.org

如果您这样做了,请记住将您的 XXX@goplus.org 电子邮件添加到 https://github.com/settings/emails 。

如何成为一个 Go+ 贡献者?您必须满足以下条件之一:

  • 至少一个实现完整功能的拉取请求。
  • 至少三个功能增强的拉取请求。
  • 至少十个任意类型的 issues 拉取请求。

你可以从哪里开始?

 

十四、拓展资料

1)官方 GitHub 地址:https://github.com/goplus/gop

2)Go+ 中文文档:https://github.com/92hackers/gop/blob/main/README_zh.md

3)许式伟:Go+ v1.x 的设计与实现丨Go+ 公开课 • 第 1 期 https://bbs.csdn.net/topics/603424088

4)Go+ 相关视频资料:https://space.bilibili.com/543831611

5)最详细的 Go+ 快速入门体验教程 https://mp.weixin.qq.com/s/IPAxcQXOe4_3S1OTDuu3kg

6)Go+ SPX保姆级入门教程-2021版 https://mp.weixin.qq.com/s/htk6MPsmW1r-9bvHhTzAgg

...全文
5225 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
哈哥撩编程 2022-03-20
  • 打赏
  • 举报
回复 1

所以 go+ 的定位也会像python那样最后发展为拥有很多贡献者贡献非常友好的第三方包那样的模式么?

真·skysys 2022-07-23
  • 举报
回复
@哈哥撩编程 我觉得是的
wuweiye0212 2021-12-02
  • 打赏
  • 举报
回复

win10 执行all.bat 在installing Go+ tools 后闪退 如何解决

_WILLPOWER_ 2021-12-06
  • 举报
回复
@wuweiye0212 你没有安装go
叨陪鲤 2021-12-01
  • 打赏
  • 举报
回复

准备试试

  • 举报
回复
@叨陪鲤 期待你的体验文章
Python小叮当 社区贡献者 2021-11-29
  • 打赏
  • 举报
回复

步骤八:Go+教程,访问404

Go+ 2021-11-29
  • 举报
回复
@Python小叮当 已替换为Go+代码仓库地址:https://github.com/goplus/gop
  • 打赏
  • 举报
回复

感谢优质内容,将收录到CSDN官方的社区周刊。往期参考 https://bbs.csdn.net/topics/603335113

1,020

社区成员

发帖
与我相关
我的任务
社区描述
Go+ 官方开发者社区。我们希望向广大的开发者和数据科学家介绍 Go+ 的定位和意义,并邀请更多开发者一起贡献代码、共建 Go+ 生态。 Go+ 官网:https://goplus.org/
其他 企业社区
社区管理员
  • Go+
  • 杨东杰
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

本社区为 Go+ 官方开发者社区。我们希望向广大的开发者和数据科学家介绍 Go+ 的定位和意义,并邀请更多开发者一起贡献代码、共建 Go+ 生态。

Go+ 官网:https://goplus.org/
GitHub地址:https://github.com/goplus/gop

试试用AI创作助手写篇文章吧