就像Perl和Golang之间的对应表一样
以下是一个「在Perl中这样,但在Golang中则这样写」的列表。
适用于那些以前使用过Perl,并刚开始学习Golang的人。非常特定狭窄的领域。
脚本和编译语言、动态类型和静态类型是完全不同的语言,本来不可比较。
然而,在基础语法的细节上,我经常在Perl中这样做,但在Golang中应该怎么做呢?于是我进行了一些研究,整理了一下,也算是对自己的学习过程的总结。
公式参考资料
-
- Perldoc
- The Go Programming Language Specification
确认版本在手边。
-
- Perl v5.16.3
- Golang 1.11.1 (Playground)
表格中的列会根据细分内容进行调整,例如在Perl中,数字和字符串的比较运算符是不同的,而在Golang中则有多种数据类型。
评论
# コメントですよ
// コメントかな?
複数行=pod
ドキュメントなんかで
使います
=cut
/*
こっちのが
みなれてるかも
*/
数学运算符
$a + $b
a + b
引く$a - $b
a - b
掛ける$a * $b
a * b
割る$a / $b
a / b
余りを求める$a % $b
a % b
インクリメント$a++
a++
デクリメント$a--
a--
文字列結合$a . $b
a + b
差不多一样。
比较运算符
$a == $b
a == b
等価 文字列$a eq $b
a == b
不等価 数値$a != $b
a != b
不等価 文字列$a ne $b
a != b
小なり$a < $b
a < b
以下$a <= $b
a <= b
大なり$a > $b
a > b
以上$a >= $b
a >= b
数据类型
#perlに真偽値は無い真=true、偽=false整数 符号なし8bit
my $a = 255
var a uint8 = 255
var a byte = 'A' //65
整数 符号なし16bitmy $a = 65535
var a uint16 = 65535
整数 符号なし32bitmy $a = 4294967295
var a uint32 = 4294967295
整数 符号なし64bituse bigint;
my $a = 18446744073709551615
var a uint64 = 18446744073709551615
整数 符号あり8bitmy $a = -128
var a int8 = -128
整数 符号あり16bitmy $a = -32768
var a int16 = -32768
整数 符号あり32bitmy $a = -2147483648
var a int32 = -2147483648
var a rune = 'あ' //12354
整数 符号あり64bituse bigint;
my $a = -9223372036854775808
var a int64 = -9223372036854775808
浮動少数 32bitmy $a = 3.14
var a float32 = 3.14
浮動少数 64bitmy $a = 0.000314159265358979
var a float64 = 0.000314159265358979
文字列my $a = "hoge"
var a string = "hoge"
配列my @a = (1, 2)
var a [2]int = [2]int{1, 2}
//配列は桁固定スライス
my @a = (1, 2)
var a []int = []int{1, 2}
//スライスは可変連想配列
my %a = ("hoge" => 1, "fuga" => 2)
var a map[string]int = map[string]int{"hoge": 1, "fuga": 2}
関数my $a = sub {
my ($in) = @_; print $in
};
&$a('hoge');
var a func(string) = func(in string) {
fmt.Print(in)
}
a("hoge")
// func(string)型の変数
-
- Perlの数値はおおよそ15桁までで、限界値はOSのライブラリに準じるとの事。それ以上はbigintモジュールを入れます。
-
- Golangの配列は値で、スライスは配列へのポインタ(+サイズなどの情報を持つ構造体)です。配列はメモリ使用効率に優れる点で、スライスと使い分けされます。
-
- Golangのbyteとruneは数値型のエイリアスですが慣例的に文字コード(Perlで言うord結果)として使われ、例えば’A’で65が、’あ’で12354が入力されます。文字列として扱うには後述の型変換が必要です。
- 後半Golangの宣言がやたら長いですが、実際はvarを省略したスコープ限定の型推論による代入(:=)を使うことが多いです。
文字串格式
-
%T
文字%s
%s
文字 スペース埋め%2s
%2s
2進数%b
%b
8進数%o
%o
10進数%d
%d
10進数 少数%f
%f
10進数 0埋め%02d
%02d
16進数 小文字%x
%x
16進数 大文字%X
%X
ポインタアドレス%p
%p
既然金额是C,那就是一样的呢。
- Perl sprintf
printf '%02d', 1;
> 01
- Golang fmt package
import "fmt"
fmt.Printf("%02d", 1)
> 01
嵌套文(包含多行字符串)
Perl是一种通用的脚本编程语言,可以用于开发各种应用程序和网站。
my $a = <<__QUERY;
SELECT hoge
FROM hage;
__QUERY
从任意的标识符到标识符之间。(上述示例为”__QUERY”)
谷歌语言 (Golang)
a := `SELECT hoge
FROM hage;`
用反引号(`)括起来。
引用/指针
my $a = \'hoge'
my $a = \1
-
無名の配列のアドレスmy $a = [1, 2]
//スライス = 配列のポインタvar a []int = []int{1, 2}
無名のハッシュのアドレスmy $a = {hoge => 1, fuga => 2}
//マップは参照型var a map[string]int = map[string]int{"hoge": 1, "fuga": 2}
スカラ変数のアドレスmy $a = \$b
# “\”でアドレス取得
var a *int = &b
// “&”でアドレス取得配列のアドレス
my $a = \@b
//bはスライスvar a []int = b
//bは配列
var a *[2]int = &b
連想配列のアドレスmy $a = \%b
var a map[string]int = b
スカラ変数のデリファレンスprint $$a
fmt.Print(*a)
配列のデリファレンスprint $$a[0]
print $a->[0]
#どちらでも良い
fmt.Print(a[0])
//配列のポインタはデリファレンスの必要なし
-
- Golangのスライスとマップはもともと参照型です。interfaceという多態性の為の仕組みがあり、Print時にStringerインターフェイスが実装されていれば実行されます。なのでPerlのように、printしたらアドレスが見れるわけではないです。
- Golangの配列のポインタはスライスかと思ったんですが、あくまで配列のポインタのようです。(配列は固定サイズなのでappendするとエラーになる)
控制结构
如果
Perl是一种高级编程语言,因其灵活性和强大的文本处理能力而受到广泛使用。
# if文
if ($a == 0) {
print "0だよ";
} elsif ($a == 1) {
print "1だよ";
} else {
print "なんだこれ";
}
# 三項演算子
print ($a == 0) ? "0だよ" : "なんだこれ";
Go语言
if a == 0 {
fmt.Print("0だよ")
} else if a == 1 {
fmt.Print("1だよ")
} else {
fmt.Print("なんだこれ")
}
// スコープ限定の変数定義
if err := SelectData(); err != nil {
fmt.Print("あかん")
}
-
- Golangは括弧が不要です。また、スコープ限定の変数が使えます。
- Golangに三項演算子はありません。
条件分岐switch可以重新表达为:分支控制结构switch。
Perl (only need one option):
Perl (只需要一个选项)。
given ($a) {
when ($_ == 1) {
print "1だよ";
}
default {
print "なんだこれ";
}
}
- Perlには元々switchはありません。新機能のgivenは「実験的機能」とされています。私は一度も使ったことがありません。
Go语言
// aを判定
switch a {
case 1:
fmt.Print("1だよ")
default:
fmt.Print("なんだこれ")
}
// 各条件内で判定
switch {
case a == 1:
fmt.Print("1だよ")
default:
fmt.Print("なんだこれ")
}
- Golangのswitchはデフォルトでbreakします。逆に以降の条件も判定したいときは、fallthroughと書きます。また、いわゆるswitch trueな使い方が正式に実装されています。
循环
用中文将以下内容转述,只需要一个选项:
Perl
for (my $i=0; $i<$a; $i++) {
print "$iです";
}
Go语言
for i:=0; i<a; i++ {
fmt.Printf("%dです", i)
}
没有什么特别要说的。
循环 while
请将以下内容用中文进行本地化解释,只需要一种选择:
Perl
# 条件に合う限りループ
while($a > 1) {
print "やばいよループしてますよー";
$a--;
}
# 無限ループ
while(1) {
print "∞";
}
Go语言
// 条件に合う限りループ
for ;i<a; {
fmt.Printf("%dです", i)
}
// 無限ループ
for {
fmt.Print("∞")
}
-
- Golangのループの制御構造は全てforで書きます。
- Golangのforは「初期化; 条件判定; 後処理」の全てが任意に省略できます。条件判定を省略すれば無限ループになります。
迭代器 数组
Perl可以用来编写多种类型的应用程序,包括Web开发、系统管理和数据处理等。它是一种流行的脚本语言,具有灵活性和强大的功能。
@values = ("a", "b", "c");
foreach my $v (@values) {
print $v;
}
> a, b, c
Golang的中文翻译是Go语言。
values := []string{"a", "b", "c"}
for i, v := range values {
fmt.Printf("%d->%s, ", i, v)
}
> 0->a, 1->b, 2->c,
遍历器 哈希/映射
Perl可以被译为”珍珠”。
%hash = (a=>1, b=>2, c=>3);
foreach my $k (keys %hash) {
print "$k\->$hash{$k}, ";
}
> c->3, a->1, b->2,
# ハッシュのキー順序は不定
Go语言
values := map[string]int{"a": 1, "b": 2, "c": 3}
for i, v := range values {
fmt.Printf("%s->%d, ", i, v)
}
> a->1, b->2, c->3,
// マップのキー順序も不定
类型转换
在Perl中,标量值基本上只有字符串或数字的区别。
# 文字列を示す「"」で囲っても、数値計算できる
my $a = "3.14";
print $a * 3;
> 9.42
# JSONに渡す時などにたまに使うint
my $int = int($str);
# 「"」で囲めば文字列扱いになる
my $str = "$int";
Golang:数值类型可以通过类型(值)进行转换。
a := 1.15
fmt.Printf("%T, %d", int(a), int(a))
> int, 1
b := int(a)
fmt.Printf("%T, %f", float64(b), float64(b))
> float64, 1.000000
文字转换为数值需要使用strconv包。
https://golang.org/pkg/strconv/
import "strconv"
// 文字列→数値
i, err := strconv.Atoi("-42")
// 数値→文字列
s := strconv.Itoa(128)
以下所述,这些数字被视为ASCII码,
因此会以Perl中chr的行为表现出来。
如果你想要”直接将数字作为字符串显示”,那它就不能被使用。
i := 65
fmt.Println(string(i))
> A
文字与ASCII码之间的转换
Perl – a high-level, interpreted programming language known for its versatility and strong text processing capabilities.
# 文字→コード
print ord('A');
> 65
# コード→文字
print chr(65);
> A
print chr(0x3042);
> あ
Golang
Golang在我看来有个特殊(初次见到)的地方。
它有一个名为byte和rune的数字类型的别名,如果将字符用单引号“’”括起来,则被认为是byte或rune;如果用双引号“””括起来,则被认为是字符串。
个人第一次在这里遇到这个问题时有点困惑,也是我想要做这个总结的原因之一。
// この場合byte型
a := 'A'
fmt.Print(a)
> 65
// この場合string型
b := "B"
fmt.Print(b)
> B
// stringは内部的にはbyte(rune)の配列
fmt.Print(b[0])
> 66
// 文字→コード
c := "あいうえお"
for _, v := range c {
fmt.Printf("%s=%x, ", string(v), v)
}
> あ=3042, い=3044, う=3046, え=3048, お=304a,
// 文字列をrangeで回した時点でrune(uint8)として扱われている
// 文字単位で表示したい場合、逆にstring(v)でキャストが必要
// Perlだと%sで暗黙にstrに変換されますが、goだと型エラーで落ちます。
// コード→文字
d := 65
fmt.Print(string(d))
> A
f := 0x3042
fmt.Print(string(f))
> あ
虽然感觉还不够完整,但暂且到这里吧。