Cwらぼっちゃ - IT技術研究ノート -

IT技術に関する記事を掲載します。

Go言語(Golang) 概要、開発環境構築

Go言語(Golang)とは

Go言語は、2009年にGoogleにて設計されたフリーかつオープンソースソースのプログラミング言語です。
2019年のエンジニアが学びたいプログラミング言語ランキング1や、年収ランキング2でも上位にランクインしています。
今回は、Go言語の特徴と、開発環境構築を行っていきます。

特徴

  • 扱いやすい
     複雑なコードを簡潔に記述することができ、初心者にとって習得しやすい言語とされています。
     また、「fmt」パッケージを利用することにより、ソースコードを自動的に整形してくれるので、非常に見やすくなります。
  • 処理速度が速い
     中間言語を介さずに直接ネイティブコード(機械語)に変換出来るので、高速でコンパイルできます。
     また、それによりメモリ消費量を抑えることができ、モバイル機器においてはバッテリー消費節約にもつながります。
  • 並列処理に強い
     並列処理が言語レベルで可能です。  これにより様々な動作を一度に行う事ができます。
  • クロスプラットフォーム対応
     Go言語はクロスプラットフォームに対応しています。
     そのため、IOSAndroidWindowsなど複数の動作環境で作動するプログラムを作成可能です。
  • マスコットキャラが可愛い(?)
     マスコットキャラが可愛いことにも定評があるようです。
     (私には可愛く見えませんが・・・)
    f:id:CwLab:20200226234920p:plain
    Renée French

開発環境構築

それでは開発環境構築を行っていきましょう。

検証環境

今回はVisual Studio Code(以下VSCode)でGo言語の構築を行います。
Go言語のIDEとしては、他にGolandがありますが、フリートライアル期間が30日間しかないので見送りました。。。

手順
1.VSCodeをインストールします

https://code.visualstudio.com/Download

2.Go言語をインストールします。

https://golang.org/dl/

3.環境変数にGOPATHを追加

環境変数の設定を行います。
といっても最新verのGo言語をインストールした場合は、自動で設定されるので、ここでは確認だけしていきます。
コントロールパネル→システムとセキュリティ→システム→システムの詳細設定→環境変数 と進めると以下の画面が表示されます。
f:id:CwLab:20200227000944p:plain Go言語にかかわるものは
・GOPATH
・Path
・GOROOT
の3つになります。
GOPATHは作業ディレクトリ(ワークスペース)で、任意の場所を指定してください。
Pathは画像の通りUSERS配下「go」フォルダ内の「bin」を設定してください。
GOROOTはGo言語をインストールした場所を設定してください。

4.コマンドプロンプトでGo言語のバージョンを確認

インストール、環境変数の設定を終えたら、コマンドプロンプトでGo言語のバージョンを確認してみましょう。
コマンドプロンプトを開いて「go version」と打ってみましょう。 f:id:CwLab:20200228201954p:plain

画像のようにGo言語のバージョンが表示されたら、構築成功です。

5.VSCodeでGo言語の拡張機能をインストール

それではVSCodeでGo言語での開発をするにあたり、必要な拡張機能をインストールしましょう。
VSCodeを起動し、拡張機能(Ctrl+Shift+X)を開いてGoで検索します。
たくさんの拡張機能がヒットしますが、以下を選択してインストールします。
f:id:CwLab:20200228202217p:plain

6.拡張機能の依存パッケージをインストール

最後にGo言語の拡張機能が依存するパッケージをインストールします。 VSCodeでコマンドパレット(Ctrl+Shift+P)を開いて「GO: Install/Update tools」で検索します。 f:id:CwLab:20200228202436p:plain

全選択し、Enterを押下してインストールします。
f:id:CwLab:20200228202503p:plain

All tools succesfull installed. You're ready to Go :). が表示されればインストール完了です。

Go言語のソースで動作確認

それでは実際にGo言語で作成したソースを動かしましょう。
以下のソース「sample.go」を作成し、VSCodeで動かします。
また、6行目にブレークポイントも仕込みます。 f:id:CwLab:20200228224637p:plain

準備が整ったらF5キーで実行しましょう。
f:id:CwLab:20200228224739p:plain

先ほど仕込んだブレークポイントで止まる事を確認したあと、再開しましょう。
f:id:CwLab:20200228224836p:plain

実行完了し、デバッグコンソールに「Hello world」と出力されました。

おわりに

手軽に開発環境の構築が出来ました。
GO言語はシンプルで分かりやすい言語なので、これからIT業界に飛び込む方にもおすすめの言語です。
また、あのGoogleにて開発が進められていることもあり、将来性もあるかと思います。
この機会にぜひ触れてみてはいかがでしょうか。

おまけ

Spring boot の言語に Kotlin を選択して Gradle に MyBatis Generator の起動タスクを登録してみたお話

はじめに

背景

この記事は流行りの技術に疎いオールドエンジニアの私がちょっと頑張ってみたお話を綴っています。
Gradle も知らなければ Kotlin も Groovy 知らない。。という状態から REST API を用いた WEBシステムをつくろうとしたのが始まりです。
フレームワークは Spring boot を使おう。言語は Kotlin。フロントは Vue.js を使おう。などと、どうせやるならやったことのない技術でやりたいと思い、手を出しました。
システムはまだまだできてませんが、O/R Mapper に MyBatis を選び、MyBatis Generator のタスク登録にとてつもなく苦労し、やっとこさジェネレートできたので備忘録も兼ねて記事を書きました。

だって記事がないんだもん。。

言語に Kotlin を選んだのがそもそもの苦労した原因でした。
Spring Initializr で Gradle やら Koltin やら MyBatis やらと選んで落としたテンプレに入っていた build.gradle が build.gradle.kts でした。
「Gradle で MyBatis Generator を実行しよう」なる記事はいくつもありました。
でもね、、でもですよ?、、これがことごとく build.gradle なんですよ。Groovy なんですよ。私の ググり力が足りていないのかもしれませんが build.gradle しかなかったんですよ。
中国サイトには載っていたような気がしますが「ちょっと何言っているかわからないです」なんです。
GitHub にも載っていたような気がしますがやっぱり「ちょっと何言っているかわからないです」なんです。
今どきのおしゃれエンジニアだったらコード見ただけで「ふふん、楽勝でしょ」ってなるのでしょうがおじさんにはどえらい高い壁に見えました。
「なんでわかんねぇーんだよ!」とツッコミが聞こえてくるようです。

What's " build.gradle.kts " ??

Kotlin DSL(Domain Specific Language) と言うようですが、要は build.gradle が Groovy で書かれるのに対して、build.gradle.kts が Kotlin で書かれるという違いです。
最初に調べていた時は技術に多少覚えのあるおじさんだったのでそりゃあ「ふふん、楽勝でしょ」って思っていましたが、いざやってみるとこれが大変。
いかに自分が " 井の中の蛞 " かを思い知らされました。

いきなりできあがり

config ファイル

ファイル名は何でも良いのですが、DB(ここでは PostgreSQL 11.5) との接続設定やら出力するクラス、そのパスなどの情報を書きます。
パスは "(ルートプロジェクト)/src/main/resources/mybatis/generatorConfig.xml" として、 generatorConfig.xml というファイル名で作成しました。

<!DOCTYPE generatorConfiguration PUBLIC
        "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <context id="kotlin" targetRuntime="MyBatis3Kotlin">
        <jdbcConnection driverClass="org.postgresql.Driver"
                        connectionURL="jdbc:postgresql://localhost:5432/hoge_db"
                        userId="hogeman"
                        password="hogehoge" />
        <javaTypeResolver />
        <javaModelGenerator
                targetPackage="com.hoge.hogeapi.model.origin"
                targetProject="src/main/kotlin">
            <property name="enableSubPackages" value="true" />
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <javaClientGenerator
                type="ANNOTATEDMAPPER"
                targetPackage="com.hoge.hogeapi.mapper.origin"
                targetProject="src/main/kotlin">
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>
        <table schema="sc_hoge" tableName="%" modelType="flat" />
    </context>
</generatorConfiguration>

xml ファイルに加えて properties ファイルを使うやり方もありますがここでは割愛します。

build.gradle.kts

はい、噂の build.gradle.kts です。

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("org.springframework.boot") version "2.2.1.RELEASE"
    id("io.spring.dependency-management") version "1.0.8.RELEASE"
    war
    kotlin("jvm") version "1.3.50"
    kotlin("plugin.spring") version "1.3.50"
}

group = "com.hoge"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_1_8

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    implementation("org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.1")
    implementation("org.mybatis.dynamic-sql:mybatis-dynamic-sql:1.1.4")
    runtimeOnly("org.postgresql:postgresql:42.1.4")
    providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
    testImplementation("org.springframework.boot:spring-boot-starter-test") {
        exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs = listOf("-Xjsr305=strict")
        jvmTarget = "1.8"
    }
}

/** -----------------------------------------------------
 * Mybatis Generator 実行タスク
 * -----------------------------------------------------*/
val mybatisMapperVersion = "4.1.5"
val mybatisGeneratorVersion = "1.4.0"
val postgresqlConnectorJavaVersion = "42.1.4"

val mybatisGenerator by configurations.creating

dependencies {
    mybatisGenerator(group="org.mybatis.generator", name="mybatis-generator-core", version=mybatisGeneratorVersion)
    mybatisGenerator(group="org.postgresql", name="postgresql", version=postgresqlConnectorJavaVersion)
    mybatisGenerator(group="tk.mybatis", name="mapper", version=mybatisMapperVersion)
}
task("mybatisGenerator") {
    doLast {
        ant.withGroovyBuilder {
            "taskdef"("name" to "mbgenerator", "classname" to "org.mybatis.generator.ant.GeneratorAntTask", "classpath" to mybatisGenerator.asPath)
        }
        ant.withGroovyBuilder {
            "mbgenerator"("overwrite" to true, "configfile" to "src/main/resources/mybatis/generatorConfig.xml", "verbose" to true)
        }
    }
}

ちなみに、お手本にした build.gradle はこちら。

plugins {
    id 'org.springframework.boot' version '2.2.1.RELEASE'
    id 'io.spring.dependency-management' version '1.0.8.RELEASE'
    id 'java'
    id 'war'
}

group = 'com.hoge'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.1'
    implementation 'org.mybatis.dynamic-sql:mybatis-dynamic-sql:1.1.4"'
    runtimeOnly 'org.postgresql:postgresql:42.1.4'
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
}

test {
    useJUnitPlatform()
}

/** -----------------------------------------------------
 * Mybatis Generator 実行タスク
 * -----------------------------------------------------*/
ext {
    mybatisMapperVersion = '4.1.5'
    mybatisGeneratorVersion = '1.4.0'
    postgresqlConnectorJavaVersion = '42.1.4'
}

configurations {
    mybatisGenerator
}

dependencies {      
    mybatisGenerator group: 'org.mybatis.generator', name: 'mybatis-generator-core', version: mybatisGeneratorVersion
    mybatisGenerator group: 'org.postgresql', name: 'postgresql', version: postgresqlConnectorJavaVersion 
    mybatisGenerator group: 'tk.mybatis', name: 'mapper', version: mybatisMapperVersion
}

task mybatisGenerator {
    doLast {
        ant.taskdef(name: 'mbgenerator', classname: 'org.mybatis.generator.ant.GeneratorAntTask', classpath: configurations.mybatisGenerator.asPath)
        ant.mbgenerator(overwrite: true, configfile: 'src/main/resources/mybatis/generatorConfig.xml', verbose: true)
    }
}

実際に参考にさせて頂いた記事とは少し違っていますが、Groovy で書くとこうでした。
違いの説明はしませんので、" Don't think, just feel! " でお願いします。
書いてみれば何のことはないただの言語の違いだけです。
ただし、「KotlinCompile」やら「withGroovyBuilder」やら、Kotlin DSL ならでは(というか Kotlin で build.gradle を書くための)記述があります。

さいごに

大事な説明をすっ飛ばして起・承・転・結な記事になってしまって申し訳なかったですが、まだまだ人に説明できるほど理解していないのでご容赦ください。
苦労して苦労して、「動いた!書こう!」というノリで記事を書きました。
当初目的としていたシステムの開発が終わるころには偉そうに説明できるくらいのレベルにはなっていたいものです。
まだまだ蛞ですが。

「それでも技術はおもしろい」

Rust言語

Rustとは

Rustは、Mozilaとコミュニティで開発されているオープンソースプログラミング言語です。C/C++の後継として目されています。 公式ドキュメントが英語だけでなく日本語もあるので、入門しやすいと思います。 おまけにブラウザ上でRustの実行が可能なサイトも載せていますので、是非お試しください。

特徴

  • C/C++に比べてメモリ周りがセキュア1
  • 静的型付け。

Cargo

RustはCargoと呼ばれるビルドシステム兼パッケージマネージャを使用します。プロジェクトのビルドや実行、依存関係にあるライブラリのダウンロード、ビルド等も可能です。ここでは簡単な説明だけしますので、詳しくは公式のドキュメントをご参照ください。

プロジェクトの作成

ターミナルで下記コマンドを実行すると、「hello_cargo」という名称のプロジェクトがカレントディレクトリの直下に作成されます。

cargo new hello_cargo --bin

実はこの時点でソースコードも生成され、実行可能な状態となっています。プロジェクトフォルダに移動してビルド、実行してみましょう。

cd hello_cargo
cargo run

実行すると、下記が出力されます。

Hello, world!

「hello_cargo/src/main.rs」ファイルが生成されているので、内容をみてみましょう。「Hello, world!」を出力するコードが書かれていることがわかると思います。基本的にはこの中身を編集することでプログラムを作成していくことになります。

fn main() {
    println!("Hello, world!");
}

記法

変数宣言

公式ドキュメントでは「変数束縛」という名称が用いられています。主に以下の要素で記法が変わります。

  • 可変性(mutable/immutable)
  • 型の明示的宣言
  • 初期化の有無
可変性

宣言の仕方によって変数の可変性が変わります。以下に例を示します。

let x = 10;         // 不可変
let mut y = 20;     // 可変

x = 30;             // コンパイルエラー
y = 40;

上記のように、mutをつけると可変、つけないと不可変となります。

型の明示的宣言

基本的な型(プリミティブ型)は明示的に宣言せずともコンパイルできます。型を明示的に宣言したいとき、構造体を使うとき等に使用することになるでしょう。

let x: i32;     // 符号付32bit整数
let y: u64;     // 符号無64bit整数

ちなみに下記のように初期化せず、型を明示的に宣言しない場合はコンパイルエラーとなります。

let x;      // コンパイルエラー

条件分岐

If文

通常は下記のように書きます。

let x = 5;
if x == 5 {
    println!("x は 5 です!");
} else if x == 6 {
    println!("x は 6 です!");
} else {
    println!("x は 5 でも 6 でもありません!");
}

そして、別の書き方として下記があります。簡単な条件分岐はこの書き方が推奨されているようです。xの値を条件にyの値を初期化する、という文です。

let x = 5;
let y = if x == 5 { 10 } else { 15 };

ループ

ループは3種類あります。

loop

単純な無限ループで使用します。

loop {
    println!("無限ループ!");
}
while

loopに条件がついたものです。逆にwhile trueがloopにあたります。

let mut x = 5;
let mut done = false;

while !done {
    x += x - 3;

    println!("{}", x);

    if x % 5 == 0 {
        done = true;
    }
}
for

初期化子、反復子で構成されます。Java等の他の言語でよくある条件部分がありません。

for x in 0..10 {
    println!("{}", x); // x: i32
}

ループ中で何回目の繰り返しかを知ることもできます。.enumerate()関数をつかいます。

for (i,j) in (5..10).enumerate() {
    println!("i = {} and j = {}", i, j);
}

iに0始まりの回数が入ります。出力は下記になります。

i = 0 and j = 5
i = 1 and j = 6
i = 2 and j = 7
i = 3 and j = 8
i = 4 and j = 9

上記ではレンジを対象にしていますが、イテレータを対象にした使い方もあります。興味があれば公式ドキュメントをご参照ください。

break

無限ループや条件に合致したときにループを抜けるための記法です。

let mut x = 5;

loop {
    x += x - 3;

    println!("{}", x);

    if x % 5 == 0 { break; }    // xが5の倍数のときにループを抜ける
}
continue

ループをスキップして、次のループに進めるための記法です。

for x in 0..10 {
    if x % 2 == 0 { continue; }    // 2の倍数(偶数)のときにスキップ

    println!("{}", x);
}

所有権

Rustには所有権(Ownership)という概念があります。変数束縛という名称にも関係してくる重要な概念なのですが、説明が難しいので省きます。C/C++のポインタぐらい重要な気がします。興味があれば公式ドキュメントをご参照ください。
https://doc.rust-jp.rs/the-rust-programming-language-ja/1.6/book/ownership.html

ベクタ

ベクタは拡張可能な配列です。インデックスにはusize型を使用する必要があります。

let v = vec![1, 2, 3, 4, 5];

let i: usize = 0;
let j: i32 = 0;

v[i];           // usizeなのでOK
v[j];           // usizeではないのでNG、コンパイルエラー

for文でイテレートに使用も可能です。

let mut v = vec![1, 2, 3, 4, 5];

for i in &v {
    println!("A reference to {}", i);
}

ここでベクタの変数vを反復子に指定するときの記法で意味が変わってきます。ここでは説明を省きます。

文字列

文字列は&strとStringの2種類あります。またいずれもUTF-8のシーケンスであることが保証されています。

&str
String
  • 可変長
  • 拡張可能

&strは.to_string()によってStringに変換され、またStringは&によって&strに型強制されます。C++のchar*とstd::stringみたいな関係になるでしょうか。ちなみにStringの.push_str()はStringの宣言時にmutをつけないとコンパイルエラーになります。

let a = "Hello";            // &'static str
println!("{}", a);

let mut b = a.to_string();  // &str -> String
b.push_str(", world!");     // 文字列追加
println!("{}", &b);         // String -> str

終わりに

前述の通りRustはC/C++の後継として注目されています。新しい概念や記法はありますが、書きやすいと思います。今後C/C++に代わる言語として使用されていくことになればどんどん普及していくことになると思います。この機会に是非触れてみてはいかがでしょうか?
ちなみに筆者はVSCodeで開発しています。開発環境構築は別途検索してみてください。

おまけ

MySQLをインストールする(Windows環境)

Windows環境へMySQLをインストールする方法を解説します。

インストーラをダウンロードする

WebブラウザMySQLのサイトを開き、Windows版のインストーラをダウンロードしましょう。

https://dev.mysql.com

f:id:CwLab:20191005195609p:plain

MySQL Downloads」をクリックします。

f:id:CwLab:20191005195921p:plain

左側、下から4つ目「MySQL Installer for Windows」をクリックします。

f:id:CwLab:20191005201300p:plain

mysql-installer-web-community”(上), “mysql-installer-community”(下)の2つのエディションが選択できます。 ここでは”mysql-installer-web-community”のインストール方法を選択します。
※このインストーラで、32ビット版/64ビット版の両方がインストールされます。
なお、それぞれのエディションの違いは以下の通りです。

エディション 説明
mysql-installer-web-community インストール実行中にネットワーク接続してファイルのダウンロードとインストールを行います。
mysql-installer-community ダウンロードするべきファイルはすべてインストーラの中に入っていて、インストール実行中はインストールのみ行います。

f:id:CwLab:20191005202953p:plain

Oracle Web account」のログインを促されますが、ログインしなくても(アカウントを持っていなくても)インストーラをダウンロードできるので、下の方の「No thanks, just start my download.」をクリックします。

クリックするとダウンロードがはじまります。

MySQLのインストール

ダウンロードしたMSI(インストーラ)ファイルをダブルクリックし、インストーラを起動させます。

f:id:CwLab:20191005211251p:plain

インストーラが起動します。「Install MySQL Products」をクリックします。

f:id:CwLab:20191005211325p:plain

ライセンスが表示されます。「I accept the license terms」にチェックを入れ、「Next」をクリックします。

f:id:CwLab:20191005212053p:plain

最新版をチェックするかどうかを問われます。
インストールの前にインストーラが最新版かどうかを確認するために、「Execute」をクリックします。

※「Skip the check for update」にチェックを入れるとこの工程をスキップできます。

f:id:CwLab:20191005214834p:plain

確認終了です。「Next」をクリックし、インストールを続行します。

f:id:CwLab:20191005215137p:plain

セットアップタイプを選択します。いろいろありますがここではデフォルトの「Developer Default」が選択されていることを確認し、「Next」をクリックします。

MySQLをインストールするフォルダを変更する場合はここで行います。 恐らく、殆どの環境では”Server only”, “Client Only”ではソフトウェア不足で何かと不便だと思いますので、”Developer Default”または”Full”がお勧めです。

f:id:CwLab:20191005221133p:plain

インストーラが、MySQLを動かすのに必要なソフトウェアをチェックしてくれます。
必要なソフトウェアがインストールされていない場合、「Execute」をクリックするとそれらをインストールしてくれます。

f:id:CwLab:20191005221623p:plain

ソフトウェアのインストールが完了したら、次にインストールするMySQL関連のソフトウェア一覧が表示されます。
インストール対象を確認し、問題なければ”Execute”をクリックしてインストールを開始します。

f:id:CwLab:20191005222742p:plain

クリックするとMySQLのダウンロードがはじまります。

f:id:CwLab:20191005223430p:plain

インストールする時期によっては、”Not all products could be downloaded successfully. Do you still wish to install the remaining products”とインストールに失敗した旨のメッセージが表示されるかもしれません。
このようなネットワーク越しインストール作業では、MySQL側のURL変更などの理由でダウンロード不能になる事はよくあります。
インストールに失敗したプロダクトは後ほど手作業でインストールを行います。

f:id:CwLab:20191005224340p:plain

インストール完了です。「Next」をクリックします。

MySQL Server 初期設定

インストールした「MySQL Server」の設定をしていきます。

f:id:CwLab:20191005225246p:plain

Server Configuration Type, Enable TCP/IP Networking, Advanced Configurationの設定を行います。 それぞれの設定項目の意味は以下の通りです。

  • Server Configuration Type
    "Development Machine"等の用途を入力すると、用途とスペックに応じて自動的に設定ファイル(my.ini)を作成します。

Server Configuration Typesの意味は以下の通りです。
開発用途ならば、”Development Machine”を選択します。

タイプ 説明
Development Machine 開発用途です。Eclipse等の統合開発環境と同一のマシンにインストールする事を想定しています。
Server Machine Apache, Tomcat等の他サーバソフトウェアと同時に動作される事を想定しています。
Dedicated Machine MySQLのみが動作するマシンを想定しまいます。ほぼ全てのメモリをMySQLに割り当てるように設定されます。
  • Eable TCP/IP Networking
    port番号の指定を行います。
    恐らく多くの場合は、デフォルトの3306で良いでしょう。

  • Advanced Configuratoin
    チェックを入れる事によって、より詳細な設定ができるようになります。
    MySQL5.6.19の場合は、ログファイルの設定がインストーラーで設定できます。

設定を確認したら「Next」をクリックします。

f:id:CwLab:20191005230929p:plain

MySQLユーザの設定を求められます。

  • Root Account Password
    MySQLの全ての設定を行えるRootユーザーのパスワードを入力します。

  • MySQL User Accounts
    一般ユーザーのアカウントが追加できます。あとで追加することも可能なので、ここでは追加しません。

設定を確認したら「Next」をクリックします。

f:id:CwLab:20191005231643p:plain

サービス名や自動起動有無を確認します。

  • Windows Service Name
    MySQLWindowsサービス名を入力します。デフォルトは「MySQL56」です。特に変更する必要はありません。

  • Start the MySQL Server at System Startup
    チェックを入れるとWindows OS起動時にMySQLサーバーが起動します。

  • Run Windows Service as …
    MySQLサービスを走らせるユーザーの設定です。「Standard System Account」が選択されていることを確認します。

設定を確認したら「Next」をクリックします。

f:id:CwLab:20191005232227p:plain

設定中です。

f:id:CwLab:20191005232959p:plain

設定完了です。「Next」をクリックします。

f:id:CwLab:20191005233030p:plain

「Finish」をクリックします。
以上で、MySQLのインストールが全て完了しました。
お疲れさまでした。

MySQL接続方法について

MySQLのデータベースに接続する方法はいくつかあります。 これについては以下のサイトがものすごくわかりやすかったので是非ご参照ください。

proengineer.internous.co.jp

Vue.jsを使ってTODOリストを作ろう!

前回の記事【Vue.jsってなに?】ではVueの環境構築から簡単にコードを触るところまでを書きました。
今回は、簡単なTODOリストを作りながらVueの機能をもう少し詳しく見ていきます。

作り始める前に

前回の記事でもお話したように、コマンド:vue createでプロジェクトを作成すると、App.vueとHelloWorld.vueの2つのvueファイルができます。
これらはコンポーネントと呼ばれ、親コンポーネントApp.vue、子コンポーネントHelloWorld.vueコンポーネントがネストした状態になっています。
画面上では、以下のように表示されています。

画面の確認方法:
powershellの場合
1. プロジェクトファイルがあるディレクトリまで行き、yarn serve コマンドを入力する。
2. サーバが起動したら http://localhost:8080/ にアクセスする。

VSCodeを使っている場合、ターミナルでyarn serveコマンドを入力すればあとは上記と同じ動作で画面確認ができます。
(個人的にはpowershellよりターミナルでやったほうがディレクトリ移動がない分スムーズで良かったです)

f:id:CwLab:20190916220047p:plain
コンポーネントがネストしている状態

HelloWorld.vueのHTML部分、 <template></template>内はすべて不要なので消します。
タイトルを書きたいのでh1タグは残しておきます。
そうすると画面上ではこうなります。

f:id:CwLab:20190916215825p:plain

この枠線の中にTODOリストを作っていきます。
これでTODOリストを作る準備は完了です。

TODOリストを作ってみよう

今回実装する機能は以下の通りです。
・タスクを追加する
・タスクを削除する
・チェックがついたタスクを一括削除する機能

タスクを追加する

タスクを追加する機能です。
ADDボタンを押下するとタスクを追加(下に表示)する機能を実装します。

その前に、前回の記事【Vue.jsってなに?】でもやったテキストボックスに入力した文字列がそのまま下に表示される処理を復習します。
-コード-

<template>
  <div>
    <h1>ToDoList</h1>
    <div>
      <label>
        <input type="textarea" v-model="newTask" />
      </label>
      <p>{{ newTask }}</p>
    </div>
  </div>
</template>

<script lang="ts">
export default class HelloWorld extends Vue {
  private newTask: string  = '';
}
</script>

-仕組み-
v-modelによる双方向データバインディングによって、テキストボックスとこのクラスのプロパティであるnewTaskが連動しており、newTaskの文字列を変更できます。pタグの中でnewTaskを呼び出すことによってテキストボックスに文字列が入力された際にリアルタイムで文字列が変更されるのを確認できます。

それでは、タスク追加機能を作っていきます。
まずはADDボタンを作成します。
ボタンにはv-on:clickを設定しておきます。イベントハンドラ名はaddTaskとします。

イベントハンドラとは、イベントが発生したときに呼び出される処理のこと。
vue.jsの場合、v-on ディレクティブを使うことで、DOM イベントの購読、イベント発火時の JavaScript の実行が可能となる。詳細

<button v-on:click="addTask">ADD</button>

次に、TODOのタスクを格納する配列を用意して、ADDボタンが押された時に呼ばれるaddTaskメソッドで、テキストボックスに入力されている値とデータバインディングされているnewTaskの値を配列に追加するイベントハンドラを設定します。
タスク1件が持つデータは、タスクの名前と完了・未完了も後ほど管理する処理を書くため、オブジェクトとして配列に追加していきます。

<script lang="ts">
export default class HelloWorld extends Vue {
  private newTask: string  = '';
  private id: number = 1; // numberは53ビット整数。浮動小数点数も格納出来る。
  private tasks: {id: number; title: string}[] = []; // TODOのタスクを格納する配列

  private addTask() {
    if (this.newTask !== '') {
      this.tasks.push({
        id: this.id++,
        title: this.newTask,
      });
    }
    this.newTask = '';
  }
}
</script>

newTask(テキストボックスの中)が空文字でないとき、idを+1してnewTaskをpush()関数を使って配列に追加するようにしました。

push()関数:配列taskssの末尾にtask(=newTask)を追加する

そして、this.newTask = ' ';でテキストボックスの中を空にしています。

次に、配列に格納したデータをリスト表示させる部分を作っていきたいと思います。
v-forディレクティブを利用します。

<ul v-for="task in tasks" :key="task.id">
  <li>
    <span>{{ task.title }}</span>
  </li>
</ul>

ulタグを1つ作り、そのulタグにv-forディレクティブを記述します。
そして、liタグの中にspan要素を作り、マスタッシュ構文でタスク名を表示させます。こんな感じですね。

マスタッシュ構文とは、Vue.jsにおける基本的なテキスト展開の方法のこと。
HTML内で{{ プロパティ名 }}で記述する。詳細

これでタスクを追加する機能の完成です。
お疲れさまでした。

タスクを削除する機能

続いてタスクを削除する機能です。
DELETEボタンを押下するとタスクを削除する機能を実装します。

まずはタスクの右側にDELETEボタンが表示されるようにします。

<div>
  <ul v-for="task in tasks" :key="task.id">
    <li>
      <span>{{ task.title }}</span>
      <button>DELETE</button>
    </li>
  </ul>
</div>

次に、ボタンにv-on:clickを設定します。イベントハンドラ名はdeleteTaskとします。

<button v-on:click="deleteTask">DELETE</button>

イベントハンドラを設定していきましょう。
DELETEボタンはタスクの数だけ存在するようになります。ですので、どのボタンに対して動作させるのかを判断させなければなりません。

そのために、deleteTaskメソッドの引数に配列tasksのindexを渡すようにします。

<script>
  private deleteTask(index)) {

  }
</script>

HTML側でも記述が必要になります。
削除ボタンのクリックイベントでdeleteTaskメソッドを呼ぶ時に配列のindexを渡すようにします。

<button v-on:click="deleteItem(index)">DELETE</button>

このdeleteTask(index)のindexがどこで取れるのかというと、
<ul v-for="task in tasks">部分になります。
ですのでこの部分を、

<ul v-for="(task,index) in tasks" :key="task.id">
  <li>***</li>
</ul>

とします。
第一引数(task)はValue、第二引数(index)はKeyが取得できます。
そして、spliceを使って配列のデータを削除させます。

<script>
private deleteTask(index) {
  this.tasks.splice(index, 1)
}
</script>

第一引数(index)が削除を始める配列のインデックス、第二引数(この場合1)は削除をする個数となります。つまり、index番目から1つ要素を削除する、という意味になります。

これで、タスクを削除する機能の完成になります。
お疲れさまでした。

チェックがついたタスクを一括削除する機能

続いてはチェックがついているタスクをまとめて削除する機能を実装します。

まず、それぞれのタスクにチェックボックスを設置します。
また、今回は一括削除する機能のためDELETEボタンは一つあればいいので、ulタグの外に出します。

<button v-on:click="deleteTask(index)">DELETE</button>

<ul v-for="task in tasks" :key="task.id">
    <li>
      <label>
        <input type="checkbox" />
        <span>{{ task.title }}</span>
      </label>                
    </li>
  </ul>

次に、オブジェクトtasksにタスクの完了・未完了を管理する部分を追加します。

<script>
  private tasks: {id: number; title: string, isChecked: boolean}[] = []; // ←isCheckedを追記

  private addTask() {
      if (this.newTask !== '') {
        this.tasks.push({
          id: this.id++,
          title: this.newTask,
          isChecked: false, // ←追記
        });
      }
      this.newTask = '';
    }
</script>

isCheckedがfalseの場合は作業か完了していない、trueの場合にはタスクが完了している、と判断します。
次はv-modelディレクティブを使って、先ほど設置したチェックボックスとisCheckedを双方向データバインディングします。
HTML側の<input>タグにv-modelを追記していきます。

<input type="checkbox" v-model="task.isChecked" />

こうすることによって、チェックボックスとisCheckedと双方向バインディングすることができます。
次に、チェックが付いている(完了した)タスクを削除するイベントハンドラを設定します。
先程使ったdeleteTaskメソッドを修正していきます。

まず、今回は一括削除ですので引数はいりません。
そして、isCheckedがfalse、つまりチェックが付いていない (完了していない) タスクのみ表示するようにします。

<button v-on:click="deleteTask">DELETE</button>

<script>
private deleteItem() {
  this.tasks = this.tasks.filter(function(task) {
    return task.isChecked === false;
  });
}
</script>

filter関数でisCheckedがfalseのものを探し出し、新しい配列(tasks)にしてreturnしています。
これでチェックが付いているタスクを一括削除する機能が完成しました。
お疲れさまでした。

完成したものがこちら!

f:id:CwLab:20190919000444p:plain

スタイルなどはつけていないのでシンプルイズザベストな仕上がりとなっております。
スタイルをつけることによってチェックボックスをつけたときに取り消し線を入れることもでき、よりTODOリストっぽくなるので
ぜひぜひお試しください。
ー完了したタスクに取り消し線を入れる方法

最後に

以上で3つの機能すべてを作り終えました。
まだまだ基礎の基礎なので、奥の深さを感じますが、導入コストが低いだけあって、スムーズに学習を始められました。

TODOリストは様々なディレクティブを活用できるのでVue.jsを学ぶにあたって最適な教材です。
ぜひ他の機能も追加してみてください。

参考文献

EC2 インスタンスへの固定IP(Elastic IP)アドレスの割り当て

はじめに

AWS EC2 インスタンスを作成、起動した際には DHCP により変動するIPアドレスが割り当てられます。
これでは作成した EC2 インスタンスを起動するたびに パブリック IP アドレスおよびパブリック DNS ホスト名 が変わっていまい、EC2 インスタンスに乗せたサービスを利用する際にはいちいち IPアドレス確認しなくてはなりません。

そこで、固定IPアドレスである EIP(Elastic IP)を利用します。
EIP を EC2 インスタンスに割り当てることで EC2 のパブリック IP アドレス およびパブリック DNS ホスト名を固定できます。

EIP の料金について

基本的に EIP の利用は無料ですが、EC2 インスタンスに割り当てていない、EC2 インスタンスに割り当てているが起動していない場合には 1時間あたり $0.005 の費用が発生します。

つまり、ただただ固定IP を確保している状態が1カ月続くと 最大 $3.72 の費用が発生します。

貴重な IP アドレスを確保しているんだからちゃんと使いなさいねということでしょうか。
EBS ボリューム も EC2 停止中であっても 費用は発生しますが、EIP も含め、有限のリソースを占有する以上はきっちりとお支払いする義務があるということですね。

EIP の確保

さて、 それでは EIP を確保し EC2 インスタンスに割り当てていきます。

EC2 ダッシュボードのナビゲーションペインから 「Elastic IP」をクリックします。

f:id:CwLab:20190912013747p:plain

コンテンツペインにある「新しいアドレスの割り当て」をクリックします。

f:id:CwLab:20190912013907p:plain

「割り当て」をクリックすると、新しい EIP を GET できます。

f:id:CwLab:20190912014054p:plain

いとも簡単にとてつもなくあっさりと GET できました。

f:id:CwLab:20190912014228p:plain

EC2 インスタンスへの EIP の割り当て

さて、確保 した EIP をさっそく EC2 インスタンス に割り当てていきます。

EIP を確保すると EIP 一覧に確保した EIP が表示されます。
※名前をつけることができるので、わかりやすい名前をつけましょう

EC2 に割り当てる EIP を選択し、「アクション」から「アドレスの関連付け」をクリックします。

f:id:CwLab:20190912015352p:plain

「アドレスの関連付け」ページから、「リソースタイプ」は "インスタンス" を選択し、該当の EC2 インスタンス を選択します。
EC2 インスタンスに割り当てている プライベート IP アドレスも選択肢、「関連付け」をクリックします。

f:id:CwLab:20190912015814p:plain

これで、該当の EC2 インスタンス のパブリック IP アドレスおよび パブリック DNS ホスト名が固定されました。

補足

EIP は確保できる数が AWS により制限されています。
つまり、公開するサーバーをたくさん作っても 確保できる EIP が限られているので、そのままでは EC2 インスタンスの数だけ EIP を確保するようなことはできません。

そんな場合は、AWS サポートページ(ここらへん) に「上限上げて」とお願いすればあっさりと上げてくれます。

AWS では いろいろ上限が決まってたりで AWS の運用をする中で 「上限上げて」だの「ペネトレーションテストさせて」など、たびたびお願いするシーンに出くわします。
面倒に思うこともありますが、私の場合は使っているリソースを見直すきっかけになったりしますし(杜撰さの露呈発言?)、サポートページのお願いフォームから簡単に申請して簡単に通るので特に苦に感じることはありませんでした。

話はそれましたが、以上が 固定IP アドレスの割り当てのお話でした。

IAM(Identity and Access Management) ユーザへの権限付与

ポリシー

AWS の権限は ポリシー と呼ばれる AWSの各種サービスへのアクセス件を制御する仕組みをIAM ユーザーやグループ、ロールに設定することで制御することができます。
*IAM ユーザー は人が使うアカウント、IAM グループは IAM ユーザーをひとまとめにしたもの、 IAM ロール は ポリシー を EC2インスタンスなどのリソースに割り当てたものを指します。

IAM のアクセス制御のためのポリシーの種類

IAM に対するアクセス制御は以下の3種類に分類されます。

  1. AWS 管理ポリシー
  2. カスタマー管理ポリシー
  3. インラインポリシー

AWS 管理ポリシー

ポリシーは AWS が事前に用意しているポリシーです。
ユーザやグループ、ロールにアタッチすることもで、ポリシーに定義されたアクセス制御ルールを適用できます。
AWS ドキュメント曰く、「AWS 管理ポリシーの中でも特に有用なカテゴリーは、職務機能用に設計されているものです。」とのことです。

主に以下の管理ポリシー(だそう)です。

職務機能 ポリシー 概要
管理者 AdministratorAccess フルアクセスが許可され、AWS のあらゆるサービスおよびリソースにアクセス許可を委任できます。
Billing (料金) Billing 請求情報の確認、支払いの設定、支払いの承認を行う必要があります。ユーザーは、AWS のサービス全体の累計されたコストをモニタリングできます。
データベース管理者 DatabaseAdministrator AWS クラウドのデータベースのセットアップ、設定、メンテナンスを行います。
データサイエンティスト DataScientist Hadoop ジョブおよびクエリを実行します。
開発者パワーユーザー PowerUserAccess アプリケーション開発タスクを実行し、AWS 対応アプリケーションの開発をサポートするリソースとサービスを作成および設定できます。
ネットワーク管理者 NetworkAdministrator ネットワークリソースの設定とメンテナンスを担当します。
セキュリティ監査人 SecurityAudit セキュリティ要件の遵守についてアカウントをモニタリングします。
サポートユーザー SupportUser AWS サポートに連絡し、サポートケースを作成して、既存のケースの状態を確認します。
システム管理者 SystemAdministrator 開発運用リソースのセットアップおよびメンテナンスを行います。
閲覧専用ユーザー ViewOnlyAccess すべてのサービスにわたるアカウントの AWS リソースや基本のメタデータのリストを表示できます。

詳細は コチラ を参照してください。引用しまくってます。

カスタマーポリシー

ポリシーマネージャーを利用して自身で作成することもできます。
また、JSONを編集して設定することもできます。

個人の所感ですが細かいアクセス制御をしたい場合は独自で作成するのが良いでしょう。

AWS が事前に用意しているポリシーは 2019/9 時点で 469 もあり、選ぶのも一苦労です。
また、そのポリシーでできること、できないことを把握するのも大変という印象を私は持ちました。
独自で必要な権限を持たせた ポリシー を作った方が手っ取り早いかと思います。

f:id:CwLab:20190903010904p:plain

インラインポリシー

インラインポリシーはユーザー、グループ、ロールそのものに埋め込まれたポリシーです。
ユーザーなどを作成する際に埋め込むことができます。

請求情報の管理を IAM ユーザーに許可する

IAM ユーザーにはデフォルトでは請求情報へのアクセスは不可になっています。
AdministratorAccess ポリシーや Billing ポリシーを IAM ユーザーやグループへアタッチしたとしても以下の通りアクセスを拒否されます。

f:id:CwLab:20190904015850p:plain

請求情報の管理を IAM ユーザーに許可するには ヘッダー のアカウント名のプルダウンを開き「マイアカウント」をクリックします。

f:id:CwLab:20190904020518p:plain

ページの中部にある「IAM ユーザー/ロールによる請求情報へのアクセス」を展開し、「編集」をクリックします。

f:id:CwLab:20190904020853p:plain

「IAM アクセスのアクティブ化」にチェックを入れ、「更新」をクリックします。

これで、Billing 等 のポリシーをアタッチされたユーザーやグループは請求情報へのアクセスが可能になります。

f:id:CwLab:20190904021225p:plain

カスタマー管理ポリシーの作成と適用

AWS 管理ポリシーのように、事前に用意されているポリシーでは賄えないような、独自の細かなアクセス制御ルールをIAMユーザーに適用するためには、カスタマー管理ポリシーを作成する必要があります。

ここでは、以下の要件のアクセス制御を行うカスタマー管理ポリシーを作成してみます。

  1. アクセス可能なサービスはEC2に限る。
  2. EC2インスタンスの起動・停止ができる。
  3. EC2インスタンスを作成・削除することはできない。

カスタマー管理ポリシーの作成

AWS マネジメントコンソール の 「サービスを検索する」 に "IAM" と入力し、Enterキー を押します。

f:id:CwLab:20190907115323p:plain

IAM コンソールに遷移しますので、サイドメニュー(専門用語でナビゲーションペインという)にある「ポリシー」をクリックします。

コンテンツ部(専門用語でコンテンツペインという)にある「ポリシーの作成」をクリックし、「ポリシーの作成」画面に遷移します。

f:id:CwLab:20190907120046p:plain

「ビジュアルエディタ」タブと「JSON」タブがありますが、今回は「ビジュアルエディタ」からポリシーを作成します。
慣れれば「JSON」の方が簡単に作成できるのですが、最初は直感的に作成できる「ビジュアルエディタ」が良いでしょう。

それでは「ビジュアルエディタ」タブから「サービスの選択」をクリックします。

f:id:CwLab:20190910020251p:plain

今回は EC2 の起動・停止のみが可能なポリシーを作成しますので、「サービスの検索」入力欄に "EC2" と入力します。

f:id:CwLab:20190910020803p:plain

入力するとフィルタがかかり、 EC2 に関連するサービスのみが一覧に表示されます。
一覧から 「EC2」 をクリックします。

f:id:CwLab:20190910021031p:plain

アクセスを許可するアクションを選択するチェックボックスが表示されます。
EC2 インスタンスの起動・停止は「書き込み」アクションですので、「書き込み」の▶マークをクリックし、詳細を展開します。

f:id:CwLab:20190910021353p:plain

展開した選択肢の中に「StartInstances」および「StopInstances」があります。
それぞれ、インスタンスの起動と停止を表すアクションです。
両方にチェックを入れます。

f:id:CwLab:20190910021734p:plain

続いて、「▶リソース」をクリックします。

f:id:CwLab:20190910021930p:plain

特定のリソース(EC2 インスタンス)に対する起動と停止を許可しますので、「ARNの追加」をクリックします。

f:id:CwLab:20190910022226p:plain

※「ARN」とは「Amazon Resource Name」のことを指し、AWSが提供するリソースを一意に識別します。

「ARNの追加」ダイアログが表示されますので、以下の通り入力すると自動で ARN を生成してくれます。

項目 入力値 備考
Region ap-northeast-1 ※東京リージョンの場合
Account 「すべて」にチェック ※特定のユーザに絞るわけではないため
Instance id [EC2ダッシュボードで確認]

※リージョンやインスタンスIDは EC2 ダッシュボードの以下の赤枠の箇所で確認できます。
 リージョンは EC2 ダッシュボードで対象のインスタンスを選択し、「説明」タブ内にある「アベイラビリティゾーン」の先頭から最後から1文字までの文字列です。
 その他、コチラ から確認できます。

f:id:CwLab:20190910025109p:plain

入力すると「EC2_instance の ARN の指定」に自動で ARN が設定されますので「追加」をクリックします。

f:id:CwLab:20190910025908p:plain

指定した ARN が元の画面の「instance」部分に表示されます。
「ポリシーの確認」をクリックします。

f:id:CwLab:20190910030208p:plain

「ポリシーの確認」画面が表示されますので、「名前」と「説明」を適当に英語でつけて、「ポリシーの作成」をクリックします。

f:id:CwLab:20190910030559p:plain

これで、カスタマー管理ポリシーの作成が完了しました。

f:id:CwLab:20190910030654p:plain

グループへアタッチ

作成したカスタマー管理ポリシーをグループへアタッチします。

「IAM Management Console」のナビゲーションペインから「グループ」をクリックします。

f:id:CwLab:20190911021102p:plain

コンテンツペインに現在存在するグループ一覧が表示されます。

ここでは "Developer" グループを選択します。

f:id:CwLab:20190911021329p:plain

「ポリシーのアタッチ」をクリックします。

f:id:CwLab:20190911021454p:plain

「フィルター」に "Sample" と入力すると、先ほど作成した 「SampleCustomerPolicy」 のみが一覧に表示されます。

f:id:CwLab:20190911021727p:plain

「SampleCustomerPolicy」にチェックを入れ、「ポリシーのアタッチ」をクリックします。

f:id:CwLab:20190911022032p:plain

これで、「Developer」グループに属するユーザーは 「SampleCustomerPolicy」のアクセス制御に則り、指定した ARN のEC2インスタンスに対して、インスタンスの起動および停止(のみ)が行えるようになります。

まとめ

これらのように AWS では、ユーザーやグループに対して細かいレベルでアクセス制御を設定することができます。
ユーザーの習熟度に応じて、できること、できないことを適切に設定することでオペレートミスによるトラブルを抑止することができます。

逆に言えば、ユーザーアカウントの使いまわしや、誰でも彼でも Administrator レベルのアクセス制御を割る振るなど、おざなりな取り扱いをすると、とてつもなく大きなリスクを抱えるものと認識しておきましょう。