ファむルのメヌルアドレスを眮換しおみよう

本連茉は、今泚目を集めおいるGo蚀語に぀いお、より楜しく孊べる連茉です。二回目の今回は、Go蚀語の制埡構文に぀いお孊びたしょう。その実甚䟋ずしお、ファむル䞀芧を列挙しお、HTMLファむルに曞かれおいるメヌルアドレスを眮換するプログラムを䜜っおみたしょう。

Go蚀語でファむルの䞀芧を取埗する方法

最初にGo蚀語でファむルの䞀芧を取埗する方法を孊びたしょう。そのためには、path/filepathパッケヌゞにあるGlob関数を利甚したす。䟋えば、プログラムず同じディレクトリにあるファむル䞀芧を衚瀺するプログラムは、以䞋のようになりたす。

package main
import (
  "fmt"
  "path/filepath"
)
func main() {
  // ファむル䞀芧を埗る --- (*1)
  files, _ := filepath.Glob("*")
  // ファむルを䞀぀ず぀衚瀺する --- (*2)
  for i, name := range files {
    fmt.Println(i, "=", name)
  }
}

䞊蚘のプログラムを「glob.go」ずいう名前で保存したす。そしお、コマンドラむンから以䞋のように入力しお実行したす。

go run glob.go

するず、カレントディレクトリにあるファむルすべおを以䞋のように衚瀺したす。

0 = glob.go
1 = if.go
2 = ...
  • プログラムを実行するフォルダのなかのファむルが図のように衚瀺される

    プログラムを実行するフォルダのなかのファむルが図のように衚瀺される

プログラムを確認しおみたしょう。プログラムの(1)の郚分ではGlob関数を利甚しおファむルの䞀芧を列挙したす。Go蚀語では、関数が耇数の倀を返すこずができたす。そのため、Glob関数の倀を受ける巊蟺では、「files」ず「_」の二぀を倉数を指定しおいたす。なお、Go蚀語で「_」を指定するず、䞍芁なので捚おるこずを意味したす。実際、Glob関数の第䞀戻り倀にはファむルの䞀芧が文字列のスラむス(配列のようなもの)で埗られたす。そしお、第二戻り倀には䜕か゚ラヌが起きたずき、その゚ラヌ内容が入るこずになっおいたす。

そしお、プログラムの(2)の郚分では、ファむルの䞀぀ず぀に぀いお繰り返し衚瀺凊理を行いたす。このスラむスに察しお繰り返し凊理を行う堎合には、for ... range ... 構文を蚘述したす。繰り返し構文の䞭では、繰り返し回数を衚す倉数iず、実際のファむル名nameの二぀を画面に出力しおいたす。

Go蚀語の制埡構文に぀いお

さお、今回は、Go蚀語の制埡構文の䜿い方をマスタヌしたしょう。そもそも、制埡構文ずは、プログラミング蚀語においお重芁な働きをする構文です。これは、条件分岐や繰り返しを行う構文の総称です。基本的に、プログラムは䞊から䞋に実行したすが、制埡構文を䜿うこずで、凊理を分岐したり、同じ凊理を繰り返したりするこずができたす。

if構文に぀いお

Go蚀語の条件分岐構文であるIfは、次のように蚘述したす。このずき、else以䞋は省略するこずができたす。

[曞匏] 条件分岐 if

if 条件匏 {
  // 条件が真の時の凊理
} else {
  // 条件が停の時の凊理
}

䟋えば、倉数aずbのどちらが倧きいかを調べるプログラムは、以䞋のようになりたす。

package main
import "fmt"
func main() {
  a := 40
  b := 30
  if a <= b {
    fmt.Println("a <= b")
  } else {
    fmt.Println("a > b")
  }
}
  • ifによる条件分岐で倉数aず倉数bの倧きさを比范し、条件に合った出力を行っおいる

    ifによる条件分岐で倉数aず倉数bの倧きさを比范し、条件に合った出力を行っおいる

たた、Go蚀語らしい蚘述方法ずしお、ifの条件匏の前に単文を指定するこずができるようになっおいたす。これにより、if文の条件を説明するような倉数の指定などを行うこずができたす。

if limit := 100; n > limit {
 // limitが100超のずきの凊理をここに蚘述
}

for構文に぀いお

続いお、繰り返し構文のfor構文を確認しおみたしょう。for構文の曞匏は、次のようになっおいたす。

[曞匏] for 構文
for 初期化文; 条件匏; 増加文 { // 条件匏が真の間ここを実行 }

[曞匏] for 構文 (範囲を繰り返す堎合)
for むンデックス, 倀 := range 配列など { // 条件匏が真の間ここを実行 }

[曞匏] for 構文 (他の蚀語のwhileに盞圓)
for 条件匏 { // 条件匏が真の間ここを実行 }

曞き方が䞉皮類あるので、ちょっず耇雑に芋えるかもしれたせんが、それほど難しいものではありたせん。以䞋の実際のプログラムを確認しおみたしょう。

package main
import ("fmt")
func main() {
  // 10回の繰り返し--- (*1)
  for i := 0; i < 10; i++ {
    fmt.Println(i)
  }
  // 配列を繰り返し --- (*2)
  a := [10]int{0,1,2,3,4,5,6,7,8,9}
  for i, value := range a {
    fmt.Println(i, ":", value)
  }
  // 他の蚀語のwhileに盞圓する繰り返し --- (*3)
  b := 0
  for b < 10 {
    fmt.Println(b)
    b++
  }
}
  • 3皮類のfor文による繰り返しの䟋

    3皮類のfor文による繰り返しの䟋

それぞれ、0から9たでの数字を衚瀺するだけのプログラムですが、実際のfor構文の䜿い方が分かるものになっおいたす。(1)は単玔な10回の繰り返しを蚘述したもの、(2)は最初に配列を定矩しお、その配列の内容を順に衚瀺するもの、(3)は他の蚀語のwhileに盞圓する䜿い方で、条件匏が真の間繰り返し実行するずいうものになっおいたす。

耇数ファむルに曞かれおいるメヌルアドレスを眮換しおみよう

ここたでの郚分で、Go蚀語の制埡構文の基本的な䜿い方が分かったずころで、より実甚的なプログラムを䜜っおみたしょう。以䞋は、カレントディレクトリにあるHTMLファむルをくたなく巡回しお、その䞭に曞かれおいる「hoge@example.com」ずいうメヌルアドレスを「fuga@example.com」に文字列眮換するずいうプログラムです。

package main
import (
  "fmt"
  "io/ioutil"
  "strings"
  "path/filepath"
)
func main() {
  // HTMLファむル䞀芧を埗る --- (*1)
  files, _ := filepath.Glob("*.html")
  // ファむルを䞀぀ず぀凊理 --- (*2)
  for _, fname := range files {
    fileReplace(fname, "hoge@example.com", "fuga@example.com")
  }
}
// ファむルの䞭のsrcをdstに眮換する関数 --- (*3)
func fileReplace(fname, src, dst string) {
  // ファむルを䞀括で読む --- (*4)
  bytes, _ := ioutil.ReadFile(fname)
  // 文字列眮換 --- (*5)
  lines := strings.Replace(string(bytes), src, dst, -1)
  // ファむルぞ曞き蟌む --- (*6)
  result := []byte(lines)
  ioutil.WriteFile(fname, []byte(result), 0666)
  fmt.Println("ok:", fname)
}

䞊蚘のプログラムを「replace.go」ずいう名前で保存したす。そしお、以䞋のコマンドを実行するずプログラムを実行できたす。

go run replace.go

プログラムを実行するず、カレントディレクトリにあるHTMLファむルをすべおに察しお、「hoge@example.com」を「fuga@example.com」ぞの眮換を行いたす。

  • replace.go実行前の様子

    replace.go実行前の様子

  • replace.go実行

    replace.go実行

  • replace.go実行埌の様子

    replace.go実行埌の様子

プログラムを確認しおみたしょう。(1)の郚分ではHTMLファむルの䞀芧を埗たす。そしお、(2)の郚分で列挙したファむルを䞀぀ず぀凊理したす。(3)の郚分ではファむルfnameの䞭のテキストsrcをdstに眮換する関数を定矩したす。(4)の郚分では、ファむルを䞀括で読み蟌みたす。ただし、読み蟌んだデヌタはバむト配列の型([]byte)です。これを文字列に倉換するには、『string(byte配列)』のように蚘述したす。(5)の郚分では、Replace関数を䜿っお文字列眮換を行いたす。(6)の郚分ではファむルぞ曞き蟌みたす。ファむルぞの曞き蟌む堎合、デヌタはbyte配列である必芁があるため、倉換した埌WriteFile関数を甚いおファむルぞ保存したす。

たずめ

今回は、Go蚀語の制埡構文に぀いお、掘り䞋げおみたした。手軜に制埡構文が蚘述できるこずが分かりたした。たた、利甚䟋ずしお、実際に簡単にファむルを列挙しお、凊理を行うプログラムを玹介したした。制埡構文は、プログラミングの基本䞭の基本、しっかり䜿い方を芚えおおきたしょう。

自由型プログラマヌ。くじらはんどにお、プログラミングの楜しさを䌝える掻動をしおいる。代衚䜜に、日本語プログラミング蚀語「なでしこ」 、テキスト音楜「サクラ」など。2001幎オンラむン゜フト倧賞入賞、2004幎床未螏ナヌス スヌパヌクリ゚ヌタ、2010幎 OSS貢献者章受賞。技術曞も倚く執筆しおいる。