戻る
トップページに戻る
Logo
Gadget Blossom 略してガジェブロ
TypeScript視点で見るGoのコード

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の書き方にも慣れていきたいと思います。