关于GO+的七个案列分析
- hello,世界
package main
import "fmt"
func main() {
fmt.Println("Hello, 世界")
}
这是hello,世界程序,要比hello,world其实要难一些,因为里面有中文!windows 下直接运行这个程序一般都有错误或是乱码出现,主要是编码的问题,倒不是程序的问题(请使用 utf-8 编码程序以及终端!)。关于安装以及其他细节可以看这篇文章—— 介绍 windows 下 go 环境的搭建,不仅仅是安装一下的问题。
从这个例子中,可以看出来,go 是通过 package(包)来实现功能或是模块分割的;控制台/终端输出要借助于 fmt 包中的 Println 函数,或是 Printf 函数;使用包之前,先导入!虽然你也许可以直接使用 print/println 函数,但是不能保证永远可以用!
go 支持单独的函数使用。所以,go 更像是 c !
程序从 main 包的 main 函数开始执行;但是 main 函数不接受参数(参数怎么处理?),没有返回值,而且貌似语句没有分号!分号实际跟 c 语言类似,是语句的分隔符,不过 go 有自动分号插入规则,所以很多时候,偶们都可以省略分号。
筛选法找素数是个不错的方法,2、3、4、5、6、7、8、9、10 ... 这些数中,第一个数 2 是素数,取出来,然后将 2 的倍数全部去掉;剩下的第一个数 3 还是素数,再去掉所有 3 的倍数,一直进行下去,就能找到很多素数。本例子也就是用的这个方法。
具体逻辑是:第一个管道记录从2开始的自然数,取第一自然数/质数 2;然后第二个管道记录从第一个管道中过滤后的所有自然数,再取一个质数 3;第三个管道取第二个管道中过滤后的数,又得一个质数;所有的管道都是无限长的,只要程序嚒有终止,这些筛选/过滤便一直在进行着。
- 处理命令行参数
package main
import (
// "fmt"
"os"
"flag" // command line option parser
)
var nFlag = flag.Bool("n", true, "末尾是否换行")
func main() {
flag.Parse(); // 解析命令行选项
s := "";
for i := 0; i < flag.NArg(); i++ {
if i > 0 {
s += " " // 单词之间用空格间隔开来
}
s += flag.Arg(i)
}
if *nFlag { // 换行与否
s += "\n"
}
// fmt.Println(flag.Args());
os.Stdout.WriteString(s);
}
// results in cmd:
> go run hello.go -n=false good morning
good morning
> go run hello.go -n=true good morning
good moring
> go run hello.go good morning
good moring
>
这个是从上面的那个——如何处理命令行参数——问题衍生出来的程序。 main 函数不像 c/c++/java 等带有参数可以处理命令行参数,go 有自己的方法。
flag 包负责处理命令行参数。这里实现的一个类似 echo 的命令,将命令行参数一个一个输出,对于最后是否换行,我们来个选项 -n=false 或是 -n=true 来决定;默认带有换行。
flag.Bool 就是获取这个 -n 选项,true/false ?使用参数前使用 flag.Parse 获取这些选项和参数,然后可以使用 flag.Args() 这个片段来处理参数,或是使用 flag.NArg() 和 flag.Arg(i) —— 一个是长度,一个是具体的值,来进行处理。
这里使用的是 os 包的 Stdout.WriteString 进行的输出,也可以使用 fmt 包中的函数进行输出。
- 斐波拉契闭包
package main
// fib returns a function that returns
// successive Fibonacci numbers.
func fib() func() int {
a, b := 0, 1
return func() int {
a, b = b, a+b
return a
}
}
func main() {
f := fib()
// Function calls are evaluated left-to-right.
println(f(), f(), f(), f(), f())
}
斐波拉契跟闭包其实嚒神马关系!斐波拉契数列是灰常出名的数列:1、1、2、3、5、8、13、...;从第三个数开始每个数均是前面两个数的和,而前两个数都是 1。习惯 c、c++ 等语言的话,e 们一般会用个循环来迭代求;go 当然也可以,不过这里使用的闭包的技术,鄙人赶脚是很巧妙的用法。
fib 是个函数,它有两个局部变量 a、b,返回值是个函数,这个函数使用着 a、b;返回值是函数现在很多语言都支持或是准备支持了,javascript、F#等等。按 c 语言的传统,函数调用完,局部(自动)变量 a、b 销毁,不能使用;然而在 go 中当 fib 返回的函数中一直在使用 fib 中的两个局部/临时变量 —— 这实际就是闭包,然后会发生神马情况呢?会将这两个变量的生存期延长,也就是说只要返回的函数还有用,这两个变量就在使用;所以,第一次调用 f、第二次调用 f 都在使用这两个变量,这两个变量的值也一直在变化,每调用一次 f ,f 返回的 a 就是一个斐波拉契数,调用几次就返回第几个 Fibonacci 数。
程序逻辑就是上面所说,不过这个例子还说明 go 的函数声明的问题,func 表明是个函数,然后写函数名,加上参数,而函数的返回值类型写在后面;函数名如果么有的话,那就是匿名函数!
- 皮亚诺整数
// Peano integers are represented by a linked
// list whose nodes contain no data
// (the nodes are the data).
// http://en.wikipedia.org/wiki/Peano_axioms
// This program demonstrates the power of Go's
// segmented stacks when doing massively
// recursive computations.
package main
import "fmt"
// Number is a pointer to a Number
type Number *Number
// The arithmetic value of a Number is the
// count of the nodes comprising the list.
// (See the count function below.)
// -------------------------------------
// Peano primitives
func zero() *Number {
return nil
}
func isZero(x *Number) bool {
return x == nil
}
func add1(x *Number) *Number {
e := new(Number)
*e = x
return e
}
func sub1(x *Number) *Number {
return *x
}
func add(x, y *Number) *Number {
if isZero(y) {
return x
}
return add(add1(x), sub1(y))
}
func mul(x, y *Number) *Number {
if isZero(x) || isZero(y) {
return zero()
}
return add(mul(x, sub1(y)), x)
}
func fact(n *Number) *Number {
if isZero(n) {
return add1(zero())
}
return mul(fact(sub1(n)), n)
}
// -------------------------------------
// Helpers to generate/count Peano integers
func gen(n int) *Number {
if n > 0 {
return add1(gen(n - 1))
}
return zero()
}
func count(x *Number) int {
if isZero(x) {
return 0
}
return count(sub1(x)) + 1
}
// -------------------------------------
// Print i! for i in [0,9]
func main() {
for i := 0; i <= 9; i++ {
f := count(fact(gen(i)))
fmt.Println(i, "! =", f)
}
}
这是一个 n!的例子,但又不是单单的一个求 n! 的例子;这个例子让 e 们赶脚到了 —— 自然数可以构造出来或是一一数出来!“皮亚诺自然数公理”:0 是一个自然数;每个自然数后面都跟有一个自然数;除 0 之外,每个自然数前面都有一个自然数;—— 0 很特殊,是第一个自然数,因为它前面没有自然数!同时例子中也反映了:阶乘依赖于自然数乘法;自然数乘法依赖于自然数加法,而自然数加法其实是个递归定义。
自然数就是一个链表,链表的第一个元素代表 0 ,第二个元素代表 1,第三个 代表 2,一直下去。10 就是一个长度为 10 的链表!求 10!的思路不再是循环一下,乘一下!而是,构造出一个长度是 10! 的链表,然后 count 一下长度,就是 10!多此一举?!这里所有的操作只建立在“加一”、“减一”和“递归”的基础之上。
- 并发求圆周率 π
// Concurrent computation of pi.
// See http://goo.gl/ZuTZM.
//
// This demonstrates Go's ability to handle
// large numbers of concurrent processes.
// It is an unreasonable way to calculate pi.
package main
import (
"fmt"
"math"
)
func main() {
fmt.Println(pi(5000))
}
// pi launches n goroutines to compute an
// approximation of pi.
func pi(n int) float64 {
ch := make(chan float64)
for k := 0; k <= n; k++ {
go term(ch, float64(k))
}
f := 0.0
for k := 0; k <= n; k++ {
f += <-ch
}
return f
}
func term(ch chan float64, k float64) {
ch <- 4 * math.Pow(-1, k) / (2*k + 1)
}
割圆术求圆周长或是圆周率,听的比较多,but,太不切实可行!不管公式怎么来的,总之有下面一个公式,本例子就是用这个公式求 π :
例子中使用了并发求每单项的值,然后将每单项的值加起来,赶脚是,加的项数越多,便越接近与真值。
go 中的管道(channel)提供了一种很方便的并发同步机制。管道是连接多个并发函数的通道,就像是水管,一端可以流进去,另一端可以流出去。这里多个函数/进程将每个单项的求值放到管道之后,谁先谁后是不确定的,然后另外一个函数/进程从管道中取值然后加起来,最后的结果便是就得的 π 的近似值。管道的同步操作已经内置,也就是不需要偶们自己去管来的。 go 是偶目前看到的写并发程序最容易的语言,么有之一!
- 并发通过筛选法求素数
// A concurrent prime sieve
package main
// Send the sequence 2, 3, 4, ... to channel 'ch'.
func Generate(ch chan<- int) {
for i := 2; ; i++ {
ch <- i // Send 'i' to channel 'ch'.
}
}
// Copy the values from channel 'in' to channel 'out',
// removing those divisible by 'prime'.
func Filter(in <-chan int, out chan<- int, prime int) {
for {
i := <-in // Receive value from 'in'.
if i%prime != 0 {
out <- i // Send 'i' to 'out'.
}
}
}
// The prime sieve: Daisy-chain Filter processes.
func main() {
ch := make(chan int) // Create a new channel.
go Generate(ch) // Launch Generate goroutine.
for i := 0; i < 10; i++ {
prime := <-ch
print(prime, "\n")
ch1 := make(chan int)
go Filter(ch, ch1, prime)
ch = ch1
}
}
- 孔明棋
// This program solves the (English) peg
// solitaire board game.
// http://en.wikipedia.org/wiki/Peg_solitaire
package main
import "fmt"
const N = 11 + 1 // length of a row (+1 for \n)
// The board must be surrounded by 2 illegal
// fields in each direction so that move()
// doesn't need to check the board boundaries.
// Periods represent illegal fields,
// ● are pegs, and ○ are holes.
var board = []rune(
`...........
...........
....●●●....
....●●●....
..●●●●●●●..
..●●●○●●●..
..●●●●●●●..
....●●●....
....●●●....
...........
...........
`)
// center is the position of the center hole if
// there is a single one; otherwise it is -1.
var center int
func init() {
n := 0
for pos, field := range board {
if field == '○' {
center = pos
n++
}
}
if n != 1 {
center = -1 // no single hole
}
}
var moves int // number of times move is called
// move tests if there is a peg at position pos that
// can jump over another peg in direction dir. If the
// move is valid, it is executed and move returns true.
// Otherwise, move returns false.
func move(pos, dir int) bool {
moves++
if board[pos] == '●' && board[pos+dir] == '●' && board[pos+2*dir] == '○' {
board[pos] = '○'
board[pos+dir] = '○'
board[pos+2*dir] = '●'
return true
}
return false
}
// unmove reverts a previously executed valid move.
func unmove(pos, dir int) {
board[pos] = '●'
board[pos+dir] = '●'
board[pos+2*dir] = '○'
}
// solve tries to find a sequence of moves such that
// there is only one peg left at the end; if center is
// >= 0, that last peg must be in the center position.
// If a solution is found, solve prints the board after
// each move in a backward fashion (i.e., the last
// board position is printed first, all the way back to
// the starting board position).
func solve() bool {
var last, n int
for pos, field := range board {
// try each board position
if field == '●' {
// found a peg
for _, dir := range [...]int{-1, -N, +1, +N} {
// try each direction
if move(pos, dir) {
// a valid move was found and executed,
// see if this new board has a solution
if solve() {
unmove(pos, dir)
println(string(board))
return true
}
unmove(pos, dir)
}
}
last = pos
n++
}
}
// tried each possible move
if n == 1 && (center < 0 || last == center) {
// there's only one peg left
println(string(board))
return true
}
// no solution found for this board
return false
}
func main() {
if !solve() {
fmt.Println("no solution found")
}
fmt.Println(moves, "moves tried")
}
需要完整的可以加微信,因为不知道如何上传资源:xiaoyu050408z 也可以互相交流
关于GO+的七个案列分析相关推荐
- python 基于情感词典的情感分析之乐,惧,惊,哀,恶,怒和未知七种情感分析
背景 情感分析是通过计算技术对文本内容的主观客观性.情绪等挖掘分析,对文本的情感偏向做出判断.目的是识别出文本中的具体情感分类,之前做文本分类都是通过深度学习或者机器学习进行文本分类,但是需要进行数据 ...
- 信息管理与信息系统专业的来龙去脉——基于六所大学个案的分析(转)
信息管理与信息系统专业的来龙去脉--基于六所大学个案的分析(转) 信息管理与信息系 2011-04-02 摘 要 在论文的前两部分,作者对信息管理与信息系统专业学科归属作了梳理,并通过对中国六所大学的 ...
- 实验七 ICMP 协议分析实验
实验七 ICMP 协议分析实验 1.ICMP 协议介绍 ICMP(Internet Control Message Protocol)是因特网控制报文协议[RFC792]的缩写,是因特网的标准协议.I ...
- python电视剧口碑分析_小案例(七):口碑分析(python)
微信公众号:机器学习养成记 搜索添加微信公众号:chenchenwings <菜鸟侦探挑战数学分析>小案例,python实现第七弹 案件回顾 商业街口碑分析 1,顾客在网络上会发表对商品或 ...
- hive窗口函数分组排序并取第一个值_Hive(七)Hive分析窗口函数
cookie1,2015-04-10,1 cookie1,2015-04-11,5 cookie1,2015-04-12,7 cookie1,2015-04-13,3 cookie1,2015-04- ...
- 【机器学习PAI实践七】文本分析算法实现新闻自动分类
一.背景 新闻分类是文本挖掘领域较为常见的场景.目前很多媒体或是内容生产商对于新闻这种文本的分类常常采用人肉打标的方式,消耗了大量的人力资源.本文尝试通过智能的文本挖掘算法对于新闻文本进行分类.无需任 ...
- oracle group by 行转列 分析执行计划
group by 子句将行划分成较小的组,然后,使用聚组函数返回每一个组的汇总信息,另外,可以使用having子句 限制返回的结果集 类似于distinct的去重,可是不明白到底俩区别?功能上grou ...
- Soot 静态分析框架(七)模块分析
Java 9里开始支持模块化,以一个独立的开源项目jigsaw而来, 具体可以参考链接, https://openjdk.java.net/projects/jigsaw/ 同时也可以参考JSR37 ...
- 机器视觉学习笔记(七)——灰度分析与变换(基于LabVIEW)
图像分析:将图像的像素灰度统计和测量技术结合,是机器可以理解图像内容,并提取特征信息以实现智能检测目的的学科,侧重于对图像内容的分析,解释和识别. 图像灰度分析是图像中最基本的内容:直方图是最基本的图 ...
最新文章
- 第十二周项目一-实现复数类中的运算符重载(3)
- MAVEN的使用入门
- linux yum yum gem,CentOS 7 gem 安装fluentd
- Android面试题集合
- 【解决方案】win10连接wifi输入密码之后用户就消失了
- pc安装linux内核,PC/104平台嵌入式Linux系统核心定制方法
- 在Angular里使用rxjs的异步API - Observable
- 高仿QQ即时聊天软件开发系列之三登录窗口用户选择下拉框
- 未来无限可能 戴尔易安信开启中国新征程
- SignalR与自托管Windows服务
- C# 连接SQL 连接字符串
- spring-data-jpa动态条件查询
- Oracle用户可要顶住了:准备好大规模补丁工作!以修补多达 433 个的新安全漏洞...
- 2020全国计算机二级office大纲,2018-2020年(最新)全国计算机等级考试二级MS Office高级应用考试大纲...
- Qt QScrollArea and layout in code
- 【第一讲】APK应用程序的解包、修改、编辑、打包及应用(转)
- nmap 扫描服务器开放了哪些端口
- 工作简历英语计算机水平怎么写,简历英语水平怎么写_简历中英语能力描述
- 【OpenCV C++】照片修改像素(尺寸大小)
- AXI中的wrap burst