用易语言可以做网站吗,青岛网站开发工资,wordpress建好站了打不开首页,建设青岛公司网站Go快速开始
Go编程语言是为工程、STEM教育和数据科学设计的。
对于工程:用儿童能掌握的最简单的语言工作。对于STEM教育:学习一门可以在未来工作中使用的工程语言。对于数据科学:用同一种语言与工程师交流。
安装方法
现在#xff0c;我们建议您从源代码安装Go。
注意:需…Go快速开始
Go编程语言是为工程、STEM教育和数据科学设计的。
对于工程:用儿童能掌握的最简单的语言工作。对于STEM教育:学习一门可以在未来工作中使用的工程语言。对于数据科学:用同一种语言与工程师交流。
安装方法
现在我们建议您从源代码安装Go。
注意:需要go1.18或更高版本
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/make.go.
在Go playground里运行
如果你不想安装Go你可以在Go playground中编写Go程序。这是体验Go的最快方式。
Go playground based on Docker: https://play.goplus.org/Go playground based on GopherJS: https://jsplay.goplus.org/
你可以和你的朋友分享你的Go代码。这是我的“Hello world”程序:
https://play.goplus.org/p/AAh_gQAKAZR.
你好世界
println Hello world将这段代码保存到一个名为“hello.gop”的文件中。现在执行:’ gop run hello.gop 。
恭喜你——你刚刚编写并执行了你的第一个Go程序!
你可以用gop build hello.gop编译一个不需要执行的程序。
有关所有支持的命令请参阅’ gop help 。
println是为数不多的内置函数之一。它将传递给它的值打印到标准输出。
详见https://tutorial.goplus.org/hello-world。
运行包含多个文件的项目文件夹
假设您有一个包含几个.gop文件的文件夹并且您想要将它们全部编译成一个程序。只要做:gop run .。
传递参数也可以所以你可以这样做:
gop run . --yourparams some_other_stuff.
然后你的程序可以像这样使用CLI参数:
import osprintln os.Args注释
# This is a single line comment.// This is a single line comment./*
This is a multiline comment.
*/变量
name : Bob
age : 20
largeNumber : int128(1 65)
println name, age
println largeNumber变量用: 声明和初始化。
变量的类型是从右边的值推断出来的。
要选择不同的类型请使用类型转换:
表达式’ T(v) ‘将值’ v 转换为“T”型。
初始化vs赋值
请注意’: ‘和’ 之间的(重要)区别。
: ‘用于声明和初始化’ 用于赋值。
age 21这段代码无法编译因为没有声明变量“age”。所有变量都需要在Go中声明。
age : 21可以在一行中修改多个变量的值。
通过这种方式可以在没有中间变量的情况下交换它们的值。
a, b : 0, 1
a, b b, a
println a, b // 1, 0Go类型
基本数据类型
boolint8 int16 int32 int int64 int128
uint8 uint16 uint32 uint uint64 uint128uintptr // similar to Cs size_tbyte // alias for uint8
rune // alias for int32, represents a Unicode code pointstringfloat32 float64complex64 complex128bigint bigratunsafe.Pointer // similar to Cs void*any // alias for Gos interface{}字符串
name : Bob
println name.len // 3
println name[0] // 66
println name[1:3] // ob
println name[:2] // Bo
println name[2:] // b// or using octal escape \### notation where # is an octal digit
println \141a // aa// Unicode can be specified directly as \u#### where # is a hex digit
// and will be converted internally to its UTF-8 representation
println \u2605 // ★字符串值是不可变的。你不能改变元素:
s : hello
s[0] H // not allowed请注意对字符串进行索引将生成一个’ byte ‘而不是’ rune ‘或另一个’ string 。
字符串可以很容易地转换为整数:
s : 12
a, err : s.int
if err ! nil {println(err)return
}
println(a:, a)b : s.int! // will panic if s isnt a valid integer
println(b:, b)字符串操作符
name : Bob
bobby : name by // is used to concatenate strings
println bobby // Bobbys : Hello
s world
println s // Hello worldGo中的所有操作符两边必须具有相同类型的值。不能连接一个整型转换为字符串:
age : 10
println age age // not allowed我们也可以将’ age ‘转换为’ string :
age : 10
println age age.stringRunes
’ rune’表示单个Unicode字符是’ int32 的别名。
rocket :
println rocket // 128640
println string(rocket) // Numbers
a : 123这将把123的值赋给’ a ‘。默认情况下’ a ‘的类型为’ int 。
您还可以使用十六进制二进制或八进制表示法来表示整数字面值:
a : 0x7B
b : 0b01111011
c : 0o173所有这些都会被赋相同的值123。它们都有类型’ int 不管你用什么符号。
Go还支持用’ _ 作为分隔符书写数字:
num : 1_000_000 // same as 1000000如果你想要一个不同类型的整数你可以使用强制转换:
a : int64(123)
b : uint8(12)
c : int128(12345)赋值浮点数的工作方式相同:
f1 : 1.0
f2 : float32(3.14)如果不显式指定类型默认情况下float字面值将具有’ float64 类型。
Float字面值也可以声明为10的幂:
f0 : 42e1 // 420
f1 : 123e-2 // 1.23
f2 : 456e2 // 45600Go内置了对有理数的支持:
a : 1r 200 // suffix r means rational
b : bigint(1 200)你可以将bool类型转换为数字类型(这在Go中不支持):
println int(true) // 1
println float64(true) // 1
println complex64(true) // (10i)切片
切片是具有相同类型的数据元素的集合。切片字面量是用方括号括起来的表达式列表。单个元素可以是使用index表达式访问。索引从“0”开始:
nums : [1, 2, 3]
println nums // [1 2 3]
println nums.len // 3
println nums[0] // 1
println nums[1:3] // [2 3]
println nums[:2] // [1 2]
println nums[2:] // [3]nums[1] 5
println nums // [1 5 3]自动推断切片文字的类型。
a : [1, 2, 3] // []int
b : [1, 2, 3.4] // []float64
c : [Hi] // []string
d : [Hi, 10] // []any
d : [] // []any强制转换切片片字面量也有效。
a : []float64([1, 2, 3]) // []float64集合
a : {Hello: 1, xsw: 3} // map[string]int
b : {Hello: 1, xsw: 3.4} // map[string]float64
c : {Hello: 1, xsw: Go} // map[string]any
d : {} // map[string]any如果没有找到键默认返回零值:
a : {Hello: 1, xsw: 3}
c : {Hello: 1, xsw: Go}
println a[bad_key] // 0
println c[bad_key] // nil您还可以检查是否存在一个键并获取它的值。
a : {Hello: 1, xsw: 3}
if v, ok : a[xsw]; ok {println its value is, v
}模块导入
模块可以使用’ import 关键字导入:
import stringsx : strings.NewReplacer(?, !).Replace(Hello, world???)
println x // Hello, world!!!模块导入别名
任何导入的模块名都可以使用别名:
import strop stringsx : strop.NewReplacer(?, !).Replace(Hello, world???)
println x // Hello, world!!!表达式和语句
If…else
在Go中’ if 语句非常简单与大多数其他语言类似。
与其他类c语言不同在条件周围没有括号并且总是需要大括号。
a : 10
b : 20
if a b {println a b
} else if a b {println a b
} else {println a b
}For循环
Go只有一个循环关键字:’ for 有几种形式。
for/-
这是最常见的形式。您可以将它与切片、映射、数字范围或自定义迭代器一起使用。
Slice for
’ for value - arr 形式用于遍历切片的元素。
numbers : [1, 3, 5, 7, 11, 13, 17]
sum : 0
for x - numbers {sum x
}
println sum // 57如果需要索引可以使用另一种形式’ for index, value - arr ’
names : [Sam, Peter]
for i, name - names {println i, name// 0 Sam// 1 Peter
}Map for
m : {one: 1, two: 2}
for key, val - m {println key, val// one 1// two 2
}
for key, _ - m {println key// one// two
}
for val - m {println val// 1// 2
}Range for
你可以在for循环中使用range expression (start:end:step)。
for i - :5 {println i// 0// 1// 2// 3// 4
}
for i - 1:5 {println i// 1// 2// 3// 4
}
for i - 1:5:2 {println i// 1// 3
}for/-/if
所有for/-形式的循环都可以有一个可选的’ if 条件。
numbers : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for num - numbers if num%3 0 {println num// 0// 3// 6// 9
}for num - :10 if num%3 0 {println num// 0// 3// 6// 9
}Condition for
sum : 0
i : 1
for i 100 {sum ii
}
println sum // 5050这种形式的循环类似于其他语言中的“while”循环。
一旦布尔条件求值为false循环将停止迭代。
同样条件周围没有括号并且总是需要大括号。
C for
for i : 0; i 10; i 2 {// Dont print 6if i 6 {continue}println i// 0// 2// 4// 8
}最后还有传统C风格的for循环。它比“while”形式更安全
因为使用后者很容易忘记更新计数器和get
陷入无限循环。
Bare for
for {// ...
}可以省略该条件从而导致无限循环。你可以使用’ break ‘或’ return 来结束循环。
错误处理
我们在Go中重新定义了错误处理规范。我们称它们为“ErrWrap表达式”:
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, errprintln addSafe(10, abc):, addSafe(10, abc)The output of this example is:
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表达式”是如何工作的?有关详细信息请参阅错误处理
函数
func add(x int, y int) int {return x y
}println add(2, 3) // 5返回多个值
func foo() (int, int) {return 2, 3
}a, b : foo()
println a // 2
println b // 3
c, _ : foo() // ignore values using _可变参数
func sum(a ...int) int {total : 0for x - a {total x}return total
}println sum(2, 3, 5) // 10输出参数可以有名称。
func sum(a ...int) (total int) {for x - a {total x}return // dont need return values if they are assigned
}println sum(2, 3, 5) // 10高阶函数
函数也可以是参数。
func square(x float64) float64 {return x*x
}func abs(x float64) float64 {if x 0 {return -x}return x
}func transform(a []float64, f func(float64) float64) []float64 {return [f(x) for x - a]
}y : transform([1, 2, 3], square)
println y // [1 4 9]z : transform([-3, 1, -5], abs)
println z // [3 1 5]Lambda表达式
你也可以使用’ lambda表达式’来定义一个匿名函数。
func transform(a []float64, f func(float64) float64) []float64 {return [f(x) for x - a]
}y : transform([1, 2, 3], x x*x)
println y // [1 4 9]z : transform([-3, 1, -5], x {if x 0 {return -x}return x
})
println z // [3 1 5]结构体
自定义的迭代器
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(callback)的范围内使用break/continue或return语句
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}推断结构类型
type Config struct {Dir stringLevel 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} 视为结构字面值会令人困惑。
您还可以在返回语句中省略结构类型。例如:
type Result struct {Text string
}func foo() *Result {return {Text: Hi, Go} // return Result{Text: Hi, Go}
}重载操作符
import math/bigtype MyBigInt struct {*big.Int
}func Int(v *big.Int) MyBigInt {return MyBigInt{v}
}func (a MyBigInt) (b MyBigInt) MyBigInt { // binary operatorreturn 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 operatorreturn MyBigInt{new(big.Int).Neg(a.Int)}
}a : Int(1r)
a Int(2r)
println a Int(3r)
println -a自动属性
Let’s see an example written in Go:
import gop/ast/goptestdoc : goptest.New(... Go code ...)!println doc.Any().FuncDecl().Name()在许多语言中有一个名为 property “的概念它有” get “和” set 方法。
假设我们有’ get property 上面的例子将是:
import gop/ast/goptestdoc : goptest.New(... Go code ...)!println doc.any.funcDecl.name在Go中我们引入了一个名为“自动属性”的概念。它是一个“get属性”但是是自动实现的。如果我们有一个名为’ Bar() ‘的方法那么我们将同时有一个名为’ Bar ‘的’ get属性’。
Go/Go 混合程序设计
这是一个展示如何在同一个包中混合Go/Go代码的示例。
在这个例子中我们有一个名为’ a.go 的Go源文件:
package mainimport fmtfunc p(a interface{}) {sayMix()fmt.Println(Hello,, a)
}我们有一个Go源文件名为’ b.gop :
func sayMix() {println Mix Go and Go
}p world你可以看到Go调用名为’ sayMix ‘的Go函数Go调用名为’ p 的Go函数。正如你在Go编程中习惯的那样这种循环引用是允许的。
运行’ gop Run . 来查看这个示例的输出:
Mix Go and Go
Hello, world在监视模式下运行Go
’ gop 命令可以在监视模式下运行以便每次更改Go文件时将其转换为Go文件:
gop watch [-gentest] [dir]默认情况下’ gop watch ‘不会转换测试文件(通常以’ _test.gop ‘结尾)。你可以指定’ -gentest 标志来强制转换所有Go文件。
从Go调用C
’ gop c ‘命令(相当于独立的’ c2go 命令)可用于将c项目转换为Go项目。’ import “C” ‘和’ import “C/xxx” 用于导入c2go转换的C项目。其中“import”C是“import”C/github.com/goplus/libc”的缩写。’ Cxxx 语法表示C风格的字符串常量。
Here is an example to show how Go interacts with C.
import CC.printf CHello, c2go!\n
C.fprintf C.stderr, CHi, %7.1f\n, 3.14在这个例子中我们调用两个C标准函数’ printf ‘和’ fprintf ‘传递一个C变量’ stderr ‘和两个C字符串形式为’ Cxxx ’ (Go语法表示C风格字符串)。
运行’ gop run . 来查看这个示例的输出:
Hello, c2go!
Hi, 3.1当然目前Go对C语言的支持只是一个预览版本还没有到实际工程中可用的程度。就libc而言目前的移民进度只有5%左右这只是一个开始。
在即将到来的Go v1.2版本计划中完全支持C语言被列为首要任务。当然对Go和Go模板的支持也在计划之中这对Go/Go混合项目来说是一个至关重要的功能增强。
数据处理
有理数
我们引入有理数作为原始Go类型。我们使用后缀“r”来表示有理字面值。例如, 1r 200 表示一个大int它的值等于 2200.
a : 1r 200
b : bigint(1 200)默认情况下’ 1r ‘的类型为’ bigint ’
4/5r表示有理常数4/5。
它的类型是’ bigrat 。
a : 4/5r
b : a - 1/3r 3 * 1/2r
println a, b // 4/5 59/30转换有理数的工作方式类似于其他基本数据类型
列表推导式
a : [x*x for x - [1, 3, 5, 7, 11]]
b : [x*x for x - [1, 3, 5, 7, 11] if x 3]
c : [iv for i, v - [1, 3, 5, 7, 11] if i%2 1]arr : [1, 2, 3, 4, 5, 6]
d : [[a, b] for a - arr if a b for b - arr if b 2]x : {x: i for i, x - [1, 3, 5, 7, 11]}
y : {x: i for i, x - [1, 3, 5, 7, 11] if i%2 1}
z : {v: k for k, v - {1: Hello, 3: Hi, 5: xsw, 7: Go} if k 3}从集合中选择数据
type student struct {name stringscore int
}students : [student{Ken, 90}, student{Jason, 80}, student{Lily, 85}]unknownScore, ok : {x.score for x - students if x.name Unknown}
jasonScore : {x.score for x - students if x.name Jason}println unknownScore, ok // 0 false
println jasonScore // 80检查集合中是否存在数据
type student struct {name stringscore int
}students : [student{Ken, 90}, student{Jason, 80}, student{Lily, 85}]hasJason : {for x - students if x.name Jason} // is any student named Jason?
hasFailed : {for x - students if x.score 60} // is any student failed?Unix shebang
现在可以使用Go程序作为shell脚本。例如:
#!/usr/bin/env -S gop runprintln Hello, Goprintln 1r 129
println 1/3r 2/7r*2arr : [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]与Go的兼容性
所有Go的特性都将被支持.
所有Go包(即使这些包使用’ cgo )都可以通过Go.导入
import (fmtstrings
)x : strings.NewReplacer(?, !).Replace(hello, world???)
fmt.Println x:, x所有Go包也可以导入到Go程序中。你需要做的就是使用’ gop ‘命令而不是’ go ’
首先让我们创建一个名为“14-Using-goplus-in-Go”的目录。
然后在其中编写一个名为foo的Go包:
package foofunc ReverseMap(m map[string]int) map[int]string {return {v: k for k, v - m}
}然后在Go包中使用它14-Using-goplus-in-Go/gomain
package mainimport (fmtgithub.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 ./...字节码 vs 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 。
References:https://tutorial.goplus.org/