TypeScript視点で見るGoのコード
ここ最近、Goを書くことが徐々に増えてきました。
これまではTypeScriptを書いていたので、Goのコードを書くときにTypeScriptの書き方を意識してしまうことがあります。
今回は、TypeScriptとGoのコードを比較しながら、TypeScript視点で見るGoのコードについてまとめていきます。
すべてを網羅できてはいませんので、あくまで一例としてご覧ください。
変数と出力
TypeScript
let message: string = "ようこそ、GadgetBlossomへ!";
console.log(message); // ようこそ、GadgetBlossomへ!
Go
package main
import "fmt"
func main() {
var message = "ようこそ、GadgetBlossomへ!"
fmt.Println(message) // ようこそ、GadgetBlossomへ!
}
定数
TypeScript
const pi: number = 3.14;
console.log(pi); // 3.14
Go
package main
import "fmt"
const pi float64 = 3.14
func main() {
fmt.Println(pi) // 3.14
}
関数
TypeScript
function add(a: number, b: number): number {
return a + b;
}
console.log(add(5, 3)); // 8
Go
package main
import "fmt"
func main() {
fmt.Println(add(5, 3)) // 8
}
func add(a int, b int) int {
return a + b
}
配列とスライス
TypeScript
let numbers: number[] = [1, 2, 3, 4, 5];
numbers.push(6);
console.log(numbers); // [1, 2, 3, 4, 5, 6]
Go
package main
import "fmt"
func main() {
numbers := []int{1, 2, 3, 4, 5}
numbers = append(numbers, 6)
fmt.Println(numbers) // [1 2 3 4 5 6]
}
配列操作 (追加)
TypeScript
let numbers: number[] = [1, 2, 3];
numbers.push(4);
numbers.unshift(0);
console.log(numbers); // [0, 1, 2, 3, 4]
Go
package main
import "fmt"
func main() {
numbers := []int{1, 2, 3}
numbers = append(numbers, 4)
numbers = append([]int{0}, numbers...)
fmt.Println(numbers) // [0 1 2 3 4]
}
配列操作 (削除)
TypeScript
let numbers: number[] = [1, 2, 3, 4, 5];
numbers.pop();
numbers.shift();
console.log(numbers); // [2, 3, 4]
Go
package main
import "fmt"
func main() {
numbers := []int{1, 2, 3, 4, 5}
numbers = numbers[:len(numbers)-1]
numbers = numbers[1:]
fmt.Println(numbers) // [2 3 4]
}
配列操作 (結合)
TypeScript
let numbers1: number[] = [1, 2];
let numbers2: number[] = [3, 4];
let numbers: number[] = numbers1.concat(numbers2);
console.log(numbers); // [1, 2, 3, 4]
Go
package main
import "fmt"
func main() {
numbers1 := []int{1, 2}
numbers2 := []int{3, 4}
numbers := append(numbers1, numbers2...)
fmt.Println(numbers) // [1 2 3 4]
}
配列操作 (更新)
TypeScript
let numbers: number[] = [1, 2, 3, 4, 5];
numbers[2] = 10;
console.log(numbers); // [1, 2, 10, 4, 5]
Go
package main
import "fmt"
func main() {
numbers := []int{1, 2, 3, 4, 5}
numbers[2] = 10
fmt.Println(numbers) // [1 2 10 4 5]
}
配列操作 (検索)
TypeScript
let numbers: number[] = [1, 2, 3, 4, 5];
let index: number = numbers.indexOf(3);
console.log(index); // 2
Go
package main
import "fmt"
func main() {
numbers := []int{1, 2, 3, 4, 5}
var index int
for i, num := range numbers {
if num == 3 {
index = i
break
}
}
fmt.Println(index) // 2
}
条件分岐 (if)
TypeScript
let num: number = 10;
if (num > 5) {
console.log("5より大きい");
} else {
console.log("5以下");
}
Go
package main
import "fmt"
func main() {
num := 10
if num > 5 {
fmt.Println("5より大きい")
} else {
fmt.Println("5以下")
}
}
条件分岐 (switch)
TypeScript
let day: number = 1;
switch (day) {
case 1:
console.log("月曜日");
break;
case 2:
console.log("火曜日");
break;
default:
console.log("その他");
}
Go
package main
import "fmt"
func main() {
day := 1
switch day {
case 1:
fmt.Println("月曜日")
case 2:
fmt.Println("火曜日")
default:
fmt.Println("その他")
}
}
繰り返し (for)
TypeScript
for (let i = 0; i < 5; i++) {
console.log(`Number: ${i}`);
}
Go
package main
import "fmt"
func main() {
for i := 0; i < 5; i++ {
fmt.Printf("Number: %d\n", i)
}
}
繰り返し (for…of / range)
let numbers: number[] = [10, 20, 30];
for (let num of numbers) {
console.log(num);
}
Go
package main
import "fmt"
func main() {
numbers := []int{10, 20, 30}
for _, num := range numbers {
fmt.Println(num)
}
}
繰り返し (for…in)
TypeScript
let person = { name: "Konta", age: 24 };
for (let key in person) {
console.log(`${key}: ${person[key]}`); // name: Konta, age: 24
}
Go
package main
import "fmt"
func main() {
person := map[string]interface{}{
"name": "Konta",
"age": 24,
}
for key, value := range person {
fmt.Printf("%s: %v\n", key, value) // name: Konta, age: 24
}
}
繰り返し (forEach)
TypeScript
let numbers: number[] = [1, 2, 3];
numbers.forEach((num, index) => {
console.log(`Index ${index}: ${num}`);
});
Go
package main
import "fmt"
func main() {
numbers := []int{1, 2, 3}
for index, num := range numbers {
fmt.Printf("Index %d: %d\n", index, num)
}
}
繰り返し (while)
TypeScript
let count: number = 0;
while (count < 5) {
console.log(`Count: ${count}`);
count++;
}
Go
package main
import "fmt"
func main() {
count := 0
for count < 5 {
fmt.Printf("Count: %d\n", count)
count++
}
}
繰り返し (do…while)
TypeScript
let count: number = 0;
do {
console.log(`Count: ${count}`);
count++;
} while (count < 5);
Go
package main
import "fmt"
func main() {
count := 0
for {
fmt.Printf("Count: %d\n", count)
count++
if count >= 5 {
break
}
}
}
ネストされた繰り返し
TypeScript
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 2; j++) {
console.log(`i: ${i}, j: ${j}`);
}
}
Go
package main
import "fmt"
func main() {
for i := 0; i < 3; i++ {
for j := 0; j < 2; j++ {
fmt.Printf("i: %d, j: %d\n", i, j)
}
}
}
オブジェクトと構造体
TypeScript
interface Person {
name: string;
age: number;
}
let person: Person = {
name: "Konta",
age: 24
};
console.log(person.name); // Konta
Go
package main
import "fmt"
type Person struct {
Name string
Age int
}
func main() {
person := Person{
Name: "Konta",
Age: 24,
}
fmt.Println(person.Name) // Konta
}
クラスとメソッド
TypeScript
class Calculator {
add(a: number, b: number): number {
return a + b;
}
}
let calc = new Calculator();
console.log(calc.add(5, 3));
Go
package main
import "fmt"
type Calculator struct{}
func (c Calculator) Add(a int, b int) int {
return a + b
}
func main() {
calc := Calculator{}
fmt.Println(calc.Add(5, 3))
}
インターフェース
TypeScript
interface Printable {
print(): void;
}
class Document implements Printable {
print(): void {
console.log("hogehoge");
}
}
Go
package main
import "fmt"
type Printable interface {
Print()
}
type Document struct{}
func (d Document) Print() {
fmt.Println("hogehoge")
}
func main() {
var p Printable = Document{}
p.Print()
}
エラーハンドリング
TypeScript
function divide(a: number, b: number): number {
if (b === 0) {
throw new Error("0で割ることはできません");
}
return a / b;
}
try {
console.log(divide(10, 0));
} catch (e) {
console.error(e.message);
}
Go
package main
import (
"errors"
"fmt"
)
func divide(a float64, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("0で割ることはできません")
}
return a / b, nil
}
func main() {
result, err := divide(10, 0)
if err != nil {
fmt.Println(err.Error())
} else {
fmt.Println(result)
}
}
非同期処理
TypeScript
async function fetchData(): Promise<string> {
return new Promise((resolve) => {
setTimeout(() => {
resolve("データを取得しました!");
}, 1000);
});
}
(async () => {
const data = await fetchData();
console.log(data); // データを取得しました!
})();
Go
package main
import (
"fmt"
"time"
)
func fetchData(c chan string) {
time.Sleep(1 * time.Second)
c <- "データを取得しました!"
}
func main() {
c := make(chan string)
go fetchData(c)
data := <-c
fmt.Println(data)
}
ジェネリクス
TypeScript
function identity<T>(arg: T): T {
return arg;
}
let output = identity<string>("Hello");
console.log(output); // "Hello"
Go
package main
import "fmt"
func identity[T any](arg T) T {
return arg
}
func main() {
output := identity[string]("Hello")
fmt.Println(output) // "Hello"
}
列挙型
TypeScript
enum Direction {
Up,
Down,
Left,
Right
}
let dir: Direction = Direction.Up;
console.log(dir); // 0
Go
package main
import "fmt"
type Direction int
const (
Up Direction = iota
Down
Left
Right
)
func main() {
var dir = Up
fmt.Println(dir) // 0
}
アクセス修飾子
TypeScript
class Person {
public name: string;
private age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
public getAge(): number {
return this.age;
}
}
let person = new Person("Konta", 24);
console.log(person.name); // Konta
console.log(person.age); // コンパイルエラー
Go
package main
type Person struct {
Name string // 大文字で始まる場合は公開
age int // 小文字で始まる場合は非公開
}
func NewPerson(name string, age int) *Person {
return &Person{
Name: name,
age: age,
}
}
func (p *Person) GetAge() int {
return p.age
}
func main() {
person := NewPerson("Konta", 24)
println(person.Name) // Konta
println(person.age) // コンパイルエラー
}
オプショナルなプロパティ
TypeScript
interface User {
name: string;
age?: number;
}
let user1: User = { name: "hogehoge" };
let user2: User = { name: "Konta", age: 24 };
console.log(user1.age); // undefined
console.log(user2.age); // 24
Go
package main
type User struct {
Name string
Age *int
}
func main() {
var age1 int
user1 := User{Name: "hogehoge", Age: &age1}
var age2 int = 24
user2 := User{Name: "Konta", Age: &age2}
fmt.Println(user1.Age) // <nil>
fmt.Println(*user2.Age) // 24
}
最後に
TypeScriptとGoは異なる言語仕様を持っていますが、基本的な構文や機能は似ている部分も多いです。
私は未だにiotaやゴルーチンなど、Goの独自の機能に慣れていない部分が数多くありますが、徐々にGoの書き方にも慣れていきたいと思います。