Go?Go!(二) 初窥Go的特性

本文深入介绍了Go语言的关键特性,包括变量定义与初始化、条件表达式、循环语句、函数定义及使用、基本类型如数组、字符串、切片和映射等。通过具体示例展示了Go语言如何简化编程流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

网上有些很好的资料,贴一些链接:

http://www.cnblogs.com/AllenDang/archive/2012/03/03/2378534.html

http://www.infoq.com/articles/google-go-primer

笔者从中选出一些个人觉得有用的特性拿来随便说说。


变量定义

GO最基本的变量声明和初始化:

var sum int // Just a declaration
var total int = 42 // A declaration with initialization

在这里,把类型写在后面的原因是为了避免C中int *a,b;这样的定义其实a和b的类型不同的问题(a是指针,b是整数)。


GO的变量定义有了自动推导类别的功能,写惯了脚本的同志肯定不会觉得name:="GOGOGO"是一个多么酷的定义+初始化,但是,对于go这种非解释的语言来说,这的确是一种进步。

另外,想要一次声明多个变量可以使用如下的方式:

var (

    i, j int
    s string
    u, v, s = 2.0, 3.0, "bar"

)

Go的条件表达式和循环语句

go的条件表达式是没有括号的C表达式,即可以写成这样:

if blablabla {

}

另外,Go也继承了C的可以在if中执行过程的方法,例如if(a= function(), a)blablabla, 在Go中只是将逗号换成了分号;


go的循环语句只支持for一种,而且,go中没有办法写出do while那种至少执行一次的循环

(在这里插一句废话,支持go语言的vim插件下载地址:http://www.vim.org/scripts/download_script.php?src_id=11734

for在go中可以这么用:

for a<b {}

for i:=0;i<10;i++{}

for i:= range("hello"){}

for{}

那个range版本的很爽,达到了脚本语言的程度,和perl、python什么的有一拼,比如遍历一个map结构(会在下文中详述):

package main                                                                                                                                 
import "fmt"
func main() {
    fmt.Println("Hello, 世界")
    _map := map[string]int{"HIT":1,"PKU":2}
    for i,value := range _map{
        fmt.Println(i, value)
    }   
}

在这一部分的最后,说说go里面的switch语句,将switch作为循环部分的压轴是绝对值得的。go中的switch语句多了如下的特性:

  1. Cases can be comma-separated lists of values, and fall-through is no longer the default behavior
    情况之间可以使用逗号分隔,并且向下透传不再是默认的行为了,这个特性意味着可以写出如下的语句:
    var result int
    switch byte {
        case 'a', 'b':
            result = 1
        default:
            result = 0

    see?no break at all
  2.  Go switches can match on much more than integers and characters. Any valid expression can be the value of a case statement
    switch在go中可以使用有效的条件表达式最为case的条件啦~~例如:
    switch result := calculate(); true {                                                                                                         
        case result < 0:
            /* negative */
        case result > 0:
            /* positive */
        default:
            /* zero */
    }
    但是,switch后面的true不要忘了~

函数

个人感觉,go的函数有一点贱贱的,为啥呢?因为它的大括号不让放在第二行T_T
但是go的函数也是有特点的:
  • 使用关键字func表明其函数的身份 func fun(){}
  • 延续了避免定义错误类型的方式 func sum(a, b int)int{return a+b}
  • 倒数第二压轴,可以返回多个数值,来一个简单的例子,例如:func multiReturn(a, b int) (int,int){return a,b}
    因为该部分在C中是不存在的,这里详细描述一下:
    多值返回的时候,返回值也可以是具名的变量:
    func divide(a, b int) (quotient, remainder int) {
        quotient = a / b
        remainder = a % b
        return

    由于这种特性,就不用再像C++中使用参数的顺序和参数是否具有const特性来区分是输入参数还是输出参数了,并且,可以使用更高端的返回值处理方法:
    if result, ok := moreMagic(); ok {
      /* Do something with result */
    }
    函数的最后一个参数可以总返回一个bool型的值,用于确定当前的函数是否正确返回了数据。 
  • 压轴大戏来啦!Go中可以存在匿名函数!真个真心牛逼,不用在内部使用的函数前面后面各种添加__了,尽管以失去了装B的乐趣为代价:)
    func makeAdder(x int) (func(int) int) {
        return func(y int) int { return x + y }//Look at me! Am I hot? Wanna a try?
    }
    func main() {
        add5 := makeAdder(5)                                                                                                                     
        add36 := makeAdder(36)
        fmt.Println("The answer:", add5(add36(1))) //=> The answer: 42
    }

Go中的基本类型

go和C比添加了一些新货(为啥总和C比较。。。其实这些新货在脚本里面都有,但是,总有一个但是,这些新货在非解释型的语言中出现,的确是新货,好吧。。。),数组,unicode的string,slice(从perl偷来的吧?)和map。

  • ARRAY:go中的array和c的一样,都不动态,他们的大小是他们类型的一部分,并且都在编译器决定。不再展开叙述
  • SLICE: 这个在perl中的翻译是切片,在这里也引用这一翻译,该数据结构的意义为:其为某个数组的片段,以下有一些定义方法:
    /* Construct a slice on ary that starts at s and is len elements long */
    s1 := ary[s:len]

    /* Omit the length to create a slice to the end of ary */
    s2 := ary[s:]

    /* Slices behave just like arrays */
    s[0] == ary[s] //=> true

    // Changing the value in a slice changes it in the array
    ary[s] = 1
    s[0] = 42
    ary[s] == 42 //=> true

    The segment of the array that the slice references can be changed by assigning a new slice to the same variable(这个不太好翻译,大概的意思就是切片引用的数数组部分能够被赋新值给原来的变量来进行改变。。。下面用一些实际的例子来阐述):
    /* Move the start of the slice forward by one, but do not move the end */
    s2 = s2[1:]
    /* Slices can only move forward */
    s2 = s2[-1:] // this is a compile error  
    可以试试如下的代码,看看结果就比较明白了:
        str := "hello"
        s := str[2:]
        fmt.Println(s, str)
        s = s[1:]
        fmt.Println(s, str)

    切片的长度是可以改变的,只要不超过其引用的数组的最大长度即可。这玩意存在的意义说白了就是能够更有效的使用数组。可以使用内建的cap函数获取切片的容量。
    下面有一个简单的例子:
    a := [...]int{1,2,3,4,5} // The ... means "whatever length the initializer has"
    len(a) //=> 5

    /* Slice from the middle */
    s := a[2:4] //=> [3 4]
    len(s), cap(s) //=> 2, 3

    /* Grow the slice */
    s = s[0:3] //=> [3 4 5]
    len(s), cap(s) //=> 3, 3

    /* Cannot grow it past its capacity */
    s = s[0:4] // this is a compile error
    Often, a slice is all that is needed for a program. In that case, a programmer need not have an array at all. Go offers two ways to make slices directly without ever referencing the underlying storage:
    说到这里,一般使用GO语言的程序员都可以抛弃数组这个东西了,切片已经满足了绝大多数的需求。

    /* literal 常量切片*/
    s1 := []int{1,2,3,4,5}

    /* empty (all zero values) 空的切片数组,可以使用内建的make函数产生*/
    s2 := make([]int, 10) // cap(s2) == len(s2) == 10
  • MAP: C中最为稀缺的基本数据结构,至于怎么使用,代码伺候:
    m := make(map[string] int) // A mapping of strings to ints
    
    /* Store some values */
    m["foo"] = 42
    m["bar"] = 30
    
    /* Read, and exit program with a runtime error if key is not present. */
    x := m["foo"]
    
    /* Read, with comma-ok check; ok will be false if key was not present. */
    x, ok := m["bar"]
    
    /* Check for presence of key, _ means "I don't care about this value." */
    _, ok := m["baz"] // ok == false
    
    /* Assign zero as a valid value */
    m["foo"] = 0;
    _, ok := m["foo"] // ok == true
    
    /* Delete a key */
    m["bar"] = 0, false
    _, ok := m["bar"] // ok == false




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值