分享
  1. 首页
  2. 文章

Go语言"奇怪用法"有哪些?

ribavnu · · 5460 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

转自:http://blog.csdn.net/delphiwcdj/article/details/16903649


本文通过对A Tour of Go的实践,总结Go语言的基础用法。

1 Go语言"奇怪用法"有哪些?


1,go的变量声明顺序是:"先写变量名,再写类型名",此与C/C++的语法孰优孰劣,可见下文解释:
http://blog.golang.org/gos-declaration-syntax

2,go是通过package来组织的(与python类似),只有package名为main的包可以包含main函数,一个可执行程序有且仅有一个main包,通过import关键字来导入其他非main包。

3,可见性规则。go语言中,使用大小写来决定该常量、变量、类型、接口、结构或函数是否可以被外部包含调用。根据约定,函数名首字母小写即为private,函数名首字母大写即为public。

4,go内置关键字(25个均为小写)。

5,函数不用先声明,即可使用。

6,在函数内部可以通过 := 隐士定义变量。(函数外必须显示使用var定义变量)

7,go程序使用UTF-8编码的纯Unicode文本编写。

8,使用big.Int的陷阱:
http://stackoverflow.com/questions/11270547/go-big-int-factorial-with-recursion

9,从技术层面讲,go语言的语句是以分号分隔的,但这些是由编译器自动添加的,不用手动输入,除非需要在同一行中写入多个语句。没有分号及只需少量的逗号和圆括号,使得go语言的程序更容易阅读。

10,go语言只有一个循环结构——for循环。

11,go里的自增运算符只有——"后++"

12,go语言中的slice用法类似python中数组,关于slice的详细用法可见:http://blog.golang.org/go-slices-usage-and-internals

13,函数也是一个值,使用匿名函数返回一个值。

14,函数闭包的使用,闭包是一个匿名函数值,会引用到其外部的变量。



/* gerryyang
 * 2013年11月23日
 */
package main
import (
 "fmt"
 "math"
 "math/big"
 "math/cmplx"
 "math/rand"
 "net/http"
 "os"
 "runtime"
 "time"
)
// Outside a function, every construct begins with a keyword (var, func, and so on) and the := construct is not available
// The var statement declares a list of variables; as in function argument lists, the type is last
var x, y, z int
var c, python, java bool
// A var declaration can include initializers, one per variable
var x1, y1, z1 int = 1, 2, 3
// If an initializer is present, the type can be omitted; the variable will take the type of the initializer
var c1, python1, java1 = true, false, "no!"
// basic types
// bool
// string
// int int8 int16 int32 int64
// uint uint8 uint16 uint32 uint64 uintptr
// byte (alias for uint8)
// rune (alias for int32, represents a Unicode code point)
// float32 float64
// complex64 complex128
var (
 ToBe bool = false
 MaxInt uint64 = 1<<64 - 1
 complex complex128 = cmplx.Sqrt(-5 + 12i)
)
// Constants are declared like variables, but with the const keyword
const Pi = 3.14
// Constants can be character, string, boolean, or numeric values
const World = "世界"
// Numeric Constants
const (
 Big = 1 << 100
 Small = Big >> 99 // 2
)
type Vertex struct {
 X int
 Y int
}
type Vertex2 struct {
 Lat, Long float64
}
var m map[string]Vertex2
// Map literals are like struct literals, but the keys are required
var m2 = map[string]Vertex2{
 "gerryyang": Vertex2{
 100, 200,
 },
 "wcdj": Vertex2{
 -300, 500,
 },
}
// If the top-level type is just a type name, you can omit it from the elements of the literal
var m3 = map[string]Vertex2{
 "math": {20, 40},
 "computer": {30, 50},
}
type Vertex3 struct {
 X, Y float64
}
type MyFloat float64
type Abser interface {
 Abs() float64
}
////////////////////////////////////////////////////////
func main() {
 fmt.Println("Hello Golang, I'm gerryyang")
 fmt.Println("The time is", time.Now())
 // To see a different number, seed the number generator; see rand.Seed
 fmt.Println("My favorite number is", rand.Intn(7))
 fmt.Printf("Now you have %g problesms\n", math.Nextafter(2, 3))
 // In Go, a name is exported if it begins with a capital letter
 fmt.Println(math.Pi)
 // Notice that the type comes after the variable name
 fmt.Println(add(42, 13))
 fmt.Println(add2(42, 13))
 // multiple results
 a, b := swap("gerry", "yang")
 fmt.Println(a, b)
 // named return
 fmt.Println(split(17))
 fmt.Println(split2(17))
 // var used
 fmt.Println(x, y, z, c, python, java)
 fmt.Println(x1, y1, z1, c1, python1, java1)
 // Inside a function, the := short assignment statement can be used in place of a var declaration with implicit type
 var x2, y2, z2 int = 1, 2, 3
 c2, python2, java2 := true, false, "yes!"
 fmt.Println(x2, y2, z2, c2, python2, java2)
 // basic types
 const f = "%T(%v)\n"
 fmt.Printf(f, ToBe, ToBe)
 fmt.Printf(f, MaxInt, MaxInt)
 fmt.Printf(f, complex, complex)
 // Constants cannot be declared using the := syntax
 const World2 = "和平"
 const Truth = true
 fmt.Println(Pi)
 fmt.Println("你好", World)
 fmt.Println("世界", World2)
 fmt.Println("Go rules?", Truth)
 // Numeric Constants
 fmt.Println(needInt(Small))
 ////fmt.Println(needInt(Big))// error, constant 1267650600228229401496703205376 overflows int
 ////fmt.Println(needInt64(Big)) // error, same as above
 ////fmt.Println(needBigInt(big.NewInt(Big)))// error, 使用big.Int貌似入参最大类型只支持int64
 fmt.Println(needFloat(Small))
 fmt.Println(needFloat(Big))
 // Go has only one looping construct, the for loop
 // The basic for loop looks as it does in C or Java, except that the ( ) are gone (they are not even optional) and the { } are required
 sum := 0
 for i := 0; i < 10; i++ {
 sum += i
 }
 fmt.Println(sum)
 // As in C or Java, you can leave the pre and post statements empty
 // At that point you can drop the semicolons: C's while is spelled for in Go
 sum1 := 1
 for sum1 < 1000 {
 sum1 += sum1
 }
 fmt.Println(sum1)
 // If you omit the loop condition it loops forever, so an infinite loop is compactly expressed
 ivar := 1
 for {
 if ivar++; ivar > 1000 {
 fmt.Println("leave out an infinite loop")
 break
 }
 }
 // The if statement looks as it does in C or Java, except that the ( ) are gone and the { } are required
 fmt.Println(sqrt(2), sqrt(-4))
 // Like for, the if statement can start with a short statement to execute before the condition
 fmt.Println(pow(3, 2, 10), pow(3, 3, 20))
 // If and else
 fmt.Println(pow2(3, 2, 10), pow2(3, 3, 20))
 ////////////////////////////////////////////////////////////
 // A struct is a collection of fields
 fmt.Println(Vertex{1, 2})
 // Struct fields are accessed using a dot
 v := Vertex{1, 2}
 v.X = 4
 fmt.Println(v)
 // Go has pointers, but no pointer arithmetic
 // Struct fields can be accessed through a struct pointer. The indirection through the pointer is transparent
 p := Vertex{1, 2}
 q := &p
 q.X = 1e9
 fmt.Println(p)
 // struct literals
 // A struct literal denotes a newly allocated struct value by listing the values of its fields
 p = Vertex{1, 2} // has type Vertex
 q = &Vertex{1, 2} // has type * Vertex
 r := Vertex{X: 1} // Y:0 is implicit
 s := Vertex{} // X:0 and Y:0
 fmt.Println(p, q, r, s)
 // The expression new(T) allocates a zeroed T value and returns a pointer to it
 // var t *T = new(T) or t := new(T)
 pv := new(Vertex)
 fmt.Println(pv)
 pv.X, pv.Y = 11, 9
 fmt.Println(pv)
 // A slice points to an array of values and also includes a length
 // []T is a slice with elements of type T
 as := []int{2, 3, 5, 7, 11, 13}
 fmt.Println("as ==", as)
 for i := 0; i < len(as); i++ {
 fmt.Printf("as[%d] == %d\n", i, as[i])
 }
 // Slices can be re-sliced, creating a new slice value that points to the same array
 // The expression: s[lo:hi]
 // evaluates to a slice of the elements from lo through hi-1, inclusive
 fmt.Println("as[1:4] ==", as[1:4])
 // missing low index implies 0
 fmt.Println("as[:3] ==", as[:3])
 // missing high index implies len(s)
 fmt.Println("as[4:] ==", as[4:])
 // Slices are created with the make function. It works by allocating a zeroed array and returning a slice that refers to that array
 // a := make([]int, 5), note, len(a) = 5
 // To specify a capacity, pass a third argument to make
 // b := make([]int, 0 , 5), note, len(b) = 0, cap(b) = 5
 // b = b[:cap(b)], note, len(b) = 5, cap(b) = 5
 // b = b[1:], note, len(b) = 4, cap(b) = 4
 s1 := make([]int, 5)
 printSlice("s1", s1)
 s2 := make([]int, 0, 5)
 printSlice("s2", s2)
 s3 := s2[:2]
 printSlice("s3", s3)
 s4 := s3[2:5]
 printSlice("s4", s4)
 // The zero value of a slice is nil
 // A nil slice has a length and capacity of 0
 var s5 []int
 fmt.Println(s5, len(s5), cap(s5))
 if s5 == nil {
 fmt.Println("slice is nil")
 }
 // The range form of the for loop iterates over a slice or map
 var s6 = []int{1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024}
 for i, v := range s6 {
 fmt.Printf("2**%d = %d\n", i, v)
 }
 // If you only want the index, drop the ", value" entirely
 for i := range s6 {
 s6[i] = 1 << uint(i)
 }
 // You can skip the index or value by assigning to _
 for _, value := range s6 {
 fmt.Printf("%d\n", value)
 }
 // A map maps keys to values
 // Maps must be created with make (not new) before use; the nil map is empty and cannot be assigned to
 m = make(map[string]Vertex2)
 m["Bell Labs"] = Vertex2{
 40.68433, -74.39967,
 }
 fmt.Println(m["Bell Labs"])
 // Map literals are like struct literals, but the keys are required
 fmt.Println(m2)
 // If the top-level type is just a type name, you can omit it from the elements of the literal
 fmt.Println(m3)
 // map
 // insert, update, retrieve, delete, test
 m4 := make(map[string]int)
 m4["date"] = 20131129
 fmt.Println("The value:", m4["date"])
 m4["date"] = m4["date"] + 1
 fmt.Println("The value:", m4["date"])
 date, ok := m4["date"]
 fmt.Println("The value:", date, "Present?", ok)
 delete(m4, "date")
 fmt.Println("The value:", m4["date"])
 date2, ok := m4["date"]
 fmt.Println("The value:", date2, "Present?", ok)
 // Function values
 // Functions are values too
 hypot := func(x, y float64) float64 {
 return math.Sqrt(x*x + y*y)
 }
 fmt.Println(hypot(3, 4))
 // Function closures
 // For example, the adder function returns a closure. Each closure is bound to its own sum variable
 pos, neg := adder(), adder()
 for i := 0; i < 10; i++ {
 fmt.Println(pos(i), neg(-2*i))
 }
 // fibonacci
 fib := fibonacci()
 for i := 0; i < 10; i++ {
 fmt.Println(fib())
 }
 // switch
 // A case body breaks automatically, unless it ends with a fallthrough statement
 switch os := runtime.GOOS; os {
 case "darwin":
 fmt.Println("OS X")
 case "linux":
 fmt.Println("Linux")
 default:
 // freebsd, openbsd
 // plan9, windows...
 fmt.Printf("%s", os)
 }
 // Switch cases evaluate cases from top to bottom, stopping when a case succeeds
 // Note: Time in the Go playground always appears to start at 2009年11月10日 23:00:00 UTC
 fmt.Println("When's Saturday?")
 today := time.Now().Weekday()
 switch time.Saturday {
 case today + 0:
 fmt.Println("Today")
 case today + 1:
 fmt.Println("Tomorrow")
 case today + 2:
 fmt.Println("In two days")
 case today + 3:
 fmt.Println("In three days")
 default:
 fmt.Println("Too far away")
 }
 // Switch without a condition is the same as switch true
 // This construct can be a clean way to write long if-then-else chains
 t_now := time.Now()
 switch {
 case t_now.Hour() < 12:
 fmt.Println("Good morning!")
 case t_now.Hour() < 17:
 fmt.Println("Good afternoon")
 default:
 fmt.Println("Good evening")
 }
 // Go does not have classes. However, you can define methods on struct types
 v3 := &Vertex3{3, 4}
 fmt.Println(v3.Abs())
 // In fact, you can define a method on any type you define in your package, not just structs
 // You cannot define a method on a type from another package, or on a basic type
 f1 := MyFloat(-math.Sqrt2)
 fmt.Println(f1.Abs())
 // Methods with pointer receivers
 // Methods can be associated with a named type or a pointer to a named type
 // We just saw two Abs methods. One on the *Vertex pointer type and the other on the MyFloat value type
 // There are two reasons to use a pointer receiver. First, to avoid copying the value on each method call (more efficient if the value type is a large struct). Second, so that the method can modify the value that its receiver points to
 v3 = &Vertex3{3, 4}
 v3.Scale(5)
 fmt.Println(v3, v3.Abs())
 // An interface type is defined by a set of methods
 // A value of interface type can hold any value that implements those methods
 var a_interface Abser
 v4 := Vertex3{3, 4}
 a_interface = f1 // a MyFloat implements Abser
 a_interface = &v4 // a *Vertex3 implements Abser
 //a_interface = v4 // a Vertex3, does Not, error!
 fmt.Println(a_interface.Abs())
 // Interfaces are satisfied implicitly
 var w Writer
 // os.Stdout implements Writer
 w = os.Stdout
 fmt.Fprintf(w, "hello, writer\n")
 // An error is anything that can describe itself as an error string. The idea is captured by the predefined, built-in interface type, error, with its single method, Error, returning a string: type error interface { Error() string }
 if err := run(); err != nil {
 fmt.Println(err)
 }
 // Web servers
 //var h Hello
 //http.ListenAndServe("localhost:4000", h)
}
/////////////////////////////////////////////
// func can be used before declare
func add(x int, y int) int {
 return x + y
}
// When two or more consecutive named function parameters share a type, you can omit the type from all but the last
func add2(x, y int) int {
 return x + y
}
// multiple results, a function can return any number of results
func swap(x, y string) (string, string) {
 return y, x
}
// In Go, functions can return multiple "result parameters", not just a single value. They can be named and act just like variables
func split(sum int) (x, y int) {
 x = sum * 4 / 9
 y = sum - x
 return y, x
}
// In Go, functions can return multiple "result parameters", not just a single value. They can be named and act just like variables
func split2(sum int) (x, y int) {
 x = sum * 4 / 9
 y = sum - x
 // If the result parameters are named, a return statement without arguments returns the current values of the results
 return
}
func needInt(x int) int { return x*10 + 1 }
func needInt64(x int64) int64 { return x*10 + 1 }
func needBigInt(x *big.Int) (result *big.Int) {
 result = new(big.Int)
 result.Set(x)
 result.Mul(result, big.NewInt(10))
 return
}
func needFloat(x float64) float64 {
 return x * 0.1
}
func sqrt(x float64) string {
 if x < 0 {
 return sqrt(-x) + "i"
 }
 return fmt.Sprint(math.Sqrt(x))
}
// Variables declared by the statement are only in scope until the end of the if
func pow(x, n, lim float64) float64 {
 if v := math.Pow(x, n); v < lim {
 return v
 }
 return lim
}
// Variables declared inside an if short statement are also available inside any of the else blocks
func pow2(x, n, lim float64) float64 {
 if v := math.Pow(x, n); v < lim {
 return v
 } else {
 fmt.Printf("%g >= %g\n", v, lim)
 }
 // can't use v here, though
 return lim
}
func printSlice(s string, x []int) {
 fmt.Printf("%s len = %d cap = %d %v\n", s, len(x), cap(x), x)
}
// Go functions may be closures. A closure is a function value that references variables from outside its body. The function may access and assign to the referenced variables; in this sense the function is "bound" to the variables
func adder() func(int) int {
 sum := 0
 return func(x int) int {
 sum += x
 return sum
 }
}
// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
 p := 0
 q := 1
 s := 0
 return func() int {
 s = p + q
 p = q
 q = s
 return s
 }
}
// The method receiver appears in its own argument list between the func keyword and the method name
func (v *Vertex3) Abs() float64 {
 return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func (f MyFloat) Abs() float64 {
 if f < 0 {
 fmt.Println("f < 0 here")
 return float64(-f)
 }
 return float64(f)
}
// Methods with pointer receivers
func (v *Vertex3) Scale(f float64) {
 v.X = v.X * f
 v.Y = v.Y * f
}
// Interfaces are satisfied implicitly
type Reader interface {
 Read(b []byte) (n int, err error)
}
type Writer interface {
 Write(b []byte) (n int, err error)
}
type ReadWriter interface {
 Reader
 Writer
}
// error control
type MyError struct {
 When time.Time
 What string
}
func (e *MyError) Error() string {
 return fmt.Sprintf("at %v, %s", e.When, e.What)
}
func run() error {
 return &MyError{
 time.Now(),
 "it didn't work",
 }
}
// Web servers
type Hello struct{}
func (h Hello) ServeHTTP(
 w http.ResponseWriter,
 r *http.Request) {
 fmt.Fprint(w, "gerryyang")
}
/*
output:
Hello Golang, I'm gerryyang
The time is 2013年12月04日 22:52:01.336562598 +0800 HKT
My favorite number is 6
Now you have 2.0000000000000004 problesms
3.141592653589793
55
55
yang gerry
10 7
7 10
0 0 0 false false false
1 2 3 true false no!
1 2 3 true false yes!
bool(false)
uint64(18446744073709551615)
complex128((2+3i))
3.14
你好 世界
世界 和平
Go rules? true
21
0.2
1.2676506002282295e+29
45
1024
leave out an infinite loop
1.4142135623730951 2i
9 20
27 >= 20
9 20
{1 2}
{4 2}
{1000000000 2}
{1 2} &{1 2} {1 0} {0 0}
&{0 0}
&{11 9}
as == [2 3 5 7 11 13]
as[0] == 2
as[1] == 3
as[2] == 5
as[3] == 7
as[4] == 11
as[5] == 13
as[1:4] == [3 5 7]
as[:3] == [2 3 5]
as[4:] == [11 13]
s1 len = 5 cap = 5 [0 0 0 0 0]
s2 len = 0 cap = 5 []
s3 len = 2 cap = 5 [0 0]
s4 len = 3 cap = 3 [0 0 0]
[] 0 0
slice is nil
2**0 = 1
2**1 = 2
2**2 = 4
2**3 = 8
2**4 = 16
2**5 = 32
2**6 = 64
2**7 = 128
2**8 = 256
2**9 = 512
2**10 = 1024
1
2
4
8
16
32
64
128
256
512
1024
{40.68433 -74.39967}
map[gerryyang:{100 200} wcdj:{-300 500}]
map[math:{20 40} computer:{30 50}]
The value: 20131129
The value: 20131130
The value: 20131130 Present? true
The value: 0
The value: 0 Present? false
5
0 0
1 -2
3 -6
6 -12
10 -20
15 -30
21 -42
28 -56
36 -72
45 -90
1
2
3
5
8
13
21
34
55
89
OS X
When's Saturday?
In three days
Good evening
5
f < 0 here
1.4142135623730951
&{15 20} 25
5
hello, writer
at 2013年12月04日 22:52:01.337206342 +0800 HKT, it didn't work
*/



有疑问加站长微信联系(非本文作者)

本文来自:CSDN博客

感谢作者:ribavnu

查看原文:Go语言"奇怪用法"有哪些?

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
5460 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏