第三章 程序的基石

        每一个程序都是有数据,对数据的处理,以及逻辑处理构成。程序中的数据又分为在程序执行中可以修改的数据叫做变量;在程序运行中不允许修改的数据叫做常量。在程序的执行过程中,通常要对数据进行运算,常见的运算有代数运算(加减乘除等)和逻辑运算(与或运算等),以及对常量和变量的赋值运算。接下来就仔细的讲解一下go语言中的变量,常量和运算符。并通过一个例子来应用在这一章学到的知识。

3.1、变量

        变量是来源于数学的一个概念,在数学表达式中,没有固定的值而可以变动的数或量。变量在计算机语言中代表,能存储计算结果或能表示值的一个抽象概念。在程序中变量可以通过变量名进行访问。在go语言程序中,定义一个变量,就会为该变量分配内存,在程序中就可以直接使用该变量。

        在计算机的语言中,变量是有类型,通常分为:布尔型、数字型、字符串型以及派生类型;布尔型的值只有true和false。数字类型通常有整型和浮点型等;派生类型包括常见的指针类型、数组类型、结构体、函数类型、切片类型、接口类型、Map类型等。go语言是静态强类型语言,同时也是编译型语言,所以,在定义变量时必须声明变量的类型。

        在go语言中,变量名由字母、数字、下划线组成,其中首字母不能为数字,声明变量的一般形式是使用var关键字,go语言中声明变量的格式是:var 变量名 变量类型。在go语言中,变量声明时如果没有设定初始值,则会自动设置为零值。下面的例子声明了一个名字为a的整形和一个名字为b的字符串:

var a int
var b string

        在go语言中除了使用var来显示的声明变量,也可以根据值自行判定变量的类型。定义格式为:var 变量名 = 变量值。上面的例子可以修改为如下方式:

var a = 0
var b = “”

        在go语言中,在函数内部有一种简短变量声明的语句的形式,可以用于变量的声明和初始化,它以"变量名 := 值或者表达式"来声明变量,变量类型根据值或者表达式自行推导。在函数中,上面的变量声明可以修改为如下方式:

package main

import “fmt”

func main() {
    a := 0
    b := “”
    fmt.Println(“Int a = “, a)
    fmt.Println(“String b = “, b)
}

        在go语言中,变量声明时当变量类型相同时,可以同时声明多个变量,声明方式如下:

  • var 变量名1, 变量名2, 变量名3 变量类型
  • var 变量名1, 变量名2, 变量名3 = 变量值1, 变量值2, 变量值3
  • 变量名1, 变量名2, 变量名3 := 变量值1, 变量值2, 变量值3

        go语言中,变量分为值类型和引用类型,所有的像int、float、bool和string这些基本类型都属于值类型,使用这些类型的变量,变量名直接指向内存中的值。对于值类型的变量,通过赋值运算把一个变量的值符给另外一个变量时,会在内存中分配一块新的空间,然后把内容复制进去:

package main

import "fmt"

func main() {
    i := 6
    j := i
    i = 10
    fmt.Println("i = ", i)
    fmt.Println("j = ", j)
}

这段代码的运行结果如下:

i = 10

j = 6

go语言的引用类型包括slice,map,channel等,他们的内部结构复杂,在声明引用类型时,除了内存申请外,还要进行相关属性的初始化工作。通常使用内置函数new来为引用类型进行初始化。引用类型的变量通常对应于一个指针,执行内存的某一块区域,当把一个引用类型变量赋值给另外一个变量时,只是让两个变量指向了同一个地址空间。

package main

import "fmt"

func main() {
    a := []int{0, 1, 2}
    b := a
    a[0] = 3
    fmt.Println(b)
}

运行结果为:[3 1 2]。我们修改了a[0]的值,因为b和a是指向同一内存空间,所以,打印b的时候的结果也变成了3 1 2 。

        go语言和其他语言一样,变量是有作用域的,根据作用域不同,变量分为全局变量和局部变量。在go语言中是根据变量声明定义所处的句法块来决定变量的作用域的。所谓句法块就是有花括号 {} 所包裹起来的一段代码。通常在一个句法块内声明的变量就是一个局部变量,比如在函数的句法块内声明的变量正能作用域函数内部,在if,for,switch等语法的句法块内声明的变量,只能作用在该语法想对应的代码块中。理解了局部变量之后,那么相对的全局变量,就是不实在 {} 句法块内声明的变量就位全局变量。全局变量通常是在package中定义,并作用域整个package内部,当然在package内的全局变量也可以通过申明为public变量的方式,在其他的包中被引用。请参考如下代码进一步理解变量的作用域:

package main

import "fmt"
var a = 1     // 全局变量,可以在整个main package中被引用

func main() {
    var b = 3    // 局部变量,只能在main函数中被引用

    if a > 0 {
        c := b // 局部变量,只能在if代码块中被引用
        fmt.Println(c)
    }
}

3.2、常量

        常量的定义变量类似,只不过常量的值在程序的运行时不允许改变。在go语言中常量使用const关键字来定义。

const World = “世界”

常量的值必须是编译期可以确定的字符、字符串、布尔或者数字等类型的值。在常量的定义是不能使用":="语法进行定义。

        关键字itoa,在go语言中是一个特殊的常量,可以认为是一个可以被编译器修改的常量。在每一个const关键字出现时,itoa被重置为0,然后在下一次const出现之前,每出现一次itoa,其所代表的数字会自动加1 。

package main

import "fmt"

func main() {
    const (
        a = iota
        b
        c
        d = "ha" //独立值,itoa增加1
        e
        f = 100
        g
        h = iota
        i
    )
    fmt.Println(a, b, c, d, e, f, g, h, i)
    const(
        x = iota
        y
        z
    )
    fmt.Println(x, y, z)
}

代码的执行结果为:

0 1 2 ha ha 100 100 7 8

0 1 2

3.3、运算符

        运算符是程序运行时执行数学或逻辑运算的主要构成,在go语言中运算符有,赋值运算符、算数运算符、关系运算符、逻辑运算符、位运算符以及其他运算符。

        最简单的赋值运算符是"=",使用赋值运算可以更新一个变量的值,最简单的赋值语句是将被赋值的变量放在=的左边,新值或者表达式放在=的右边。

x = 1
*p = true
person.name = “Bob”
count[x] = count[x] * 3

        此外,特定的二元运算符和赋值语句可以复合成一个简洁的方式,可以省去对变量表达式的重复计算,例如上面例子中最后一条语句可以简化为如下语句:

count[x] *= 3

        数字变量也可以支持"++"递增和"--"递减语句。自增和自减是语句,而不是表达式,因此,x = i++是错误的写法。

        元组赋值是另一种形式的赋值语句,它允许同时更新多个变量的值。在进行赋值之前,赋值语句的右边表达式会先进行运算,然后会统一更新左边的变量。这对处理同时出现在元组左右两边的变量处理有很大的帮助,比如,我们可以按照下面的方式进行元组变量值的交换:

x, y = y, x

3.4、最大公约数计算

        接下来通过最大公约数的计算来综合的练习一下在本章中学到的知识。计算最大公约数的方法,比较常用的有辗转相除法、穷举法、更相减损法、Stein算法,在这里通过元组赋值来实现辗转相除法。算法概要如下:

  • 定义两个变量a和b,a做被除数,b做除数,并将较大的数放到a,较小的数放到b。
  • 计算a除以b的余数,并将计算结果赋值给b,将b赋值给a。
  • 如果b不等于0,重复执行上面的步骤。
  • b等于0的时候,a就是这两个数的最大公约数。

采用元组赋值的特性,我们可以很方便通过数值交换的方式实现上面的算法,示例代码和执行结果如下:

package main

import "fmt"
func gcd(a, b int) int {
    for b != 0 {
        a, b = b, a % b
    }
    return a
}

func main() {
    res := gcd(10, 15)
    fmt.Println(res)
}

执行结果如下:

5

3.5、命令行参数

        go语言是一种编译语言,可以将go语言的代码编译成二进制文件,在需要的时候多次运行,来进行计算。接下来就将上面的最大公约数计算的代码增加命令行的参数,以便于我们重复使用。在go语言中获取命令的参数可以通过os库或者flag库获得,相对于os库的简洁来说,flag库可以指定命令行参数的类型,和对参数使用方式进行说明和描述。在这个例子中使用os来获取参数。

        os库通过使用变量Args来获取命令参数,os.Args返回的是一个字符串数组,其中第一个参数是执行文件本身。从第二个参数开始是我们在命令行中输入参数,示例代码如下:

package main

import (
    "fmt"
    "os"
    "strconv"
func gcd(a, b int) int {
    for b != 0 {
        a, b = b, a % b
    }
    return a
}

func main() {
    l := len(os.Args)
    if l >= 3 {
        a, _ := strconv.Atoi(os.Args[1])     //将字符串转换为int
        b, _ := strconv.Atoi(os.Args[2])
        if b > a {
            a, b = b, a
        }
        res := gcd(a, b)
        fmt.Println("最大公约数是:", res)
    } else {
        fmt.Println("参数不正确,请检查输入的参数")
    }
}

在代码的所在目录下输入go run main.go 10 15执行结果如下:

最大公约数是:5

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值