メインコンテンツに移動
フェリス

数年前から話題になってきたRustとDeno。あまり情報収集が得意ではないわたしにもとどいた新しめのプログラミング言語。。。
と思いきやRustは2010年にはすでにあったようです。
Denoのほうは2018年から登場しているので、こちらは新しい言語ですね。
 

今回はRustについて、いろいろ書いていこうと思います

Rustとは?

コンパイラーやOSなどの低レイヤーに関する詳細な記述が可能で、メモリ管理ができるそうなのでC言語やC++の代わりとして期待されているようです。
プログラマーのためのコミュニティサイトであるStack Overflowが毎年行っているアンケートでは2023年の求められる言語 + 賞賛される言語としてRustが高い数値となっています。
「使ったことがないけど使いたい(Desired)」では30%ほどで上から6番目ですが、「実際に使ってみて今後も使いたい(Admired)」になると84%を超え上から1番目の集計結果となっています。
 

求められる言語 + 賞賛される言語

引用元:https://survey.stackoverflow.co/2023/#programming-scripting-and-markup-languages

Rustの特徴

  • 処理速度が速い
  • 並行処理が可能
  • 安全性が高い

ということです。簡単に説明していきます。
 

処理速度が速い


機械語にコンパイラするネイティブコンパイラ言語であること、ガベージコレクションを持たないため不要メモリの開放ができる、抽象化を「ゼロコスト」で行うことができることが上げられるため、高速処理が可能となっています。

並行処理が可能

複数処理を並行で行うマルチスレッドに対応しているため、タスク完了の時間が短縮することが可能です。

安全性が高い


ガベージコレクションがないため、メモリ管理を手動で行う必要があり、C言語の場合はそこにリスクがあると言われています。Rustの場合は「所有者」というメモリ管理用の仕組みが存在するため、メモリの多重解放や解放漏れが起こらないようになっているようです。


基本的にどの特徴もC言語と比べて優秀と、どのサイトでも記載されていました。
ただし、ガベージコレクションがないことでメモリ管理する手間が発生したりマルチスレッドの場合、デッドロックが起きる可能性があるなどリスクはあるようです。

Rust開発

Webアプリケーション
OS
ゲーム
など、C言語やC++で実装しているものは開発に向いていると言えます。

チュートリアル

https://www.rust-lang.org/ja/learn/get-started?_fsi=NvY0Wx0K
こちらに日本語版のRustチュートリアルがありますが、Linuxでやりたいので調べながらやっていきます。

・・・・

・・・・

・・・・

と思いましたが、チュートリアルはHello Worldまでなのでそこからmysqlの接続とselectまでやっていきます。

Rust環境構築

Rustをインストールする
まずは下記コマンドを実行します。
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

途中デフォルトインストールか、カスタマイズインストールか、キャンセルかを選ぶため止まります。
カスタマイズはインストールパス等を変えられるようですが、今回はデフォルトのHOMEで問題ないのでデフォルトインストールを選びます。

インストールしたら再ログインをして「rustup」を実行します。
 

rustup

 

Rustは6週間くらいで新バージョンがリリースされているそうなので、アップデートコマンドも実行します。
 

rustup update

 

新しいプロジェクトを作成する

cargo new rust_mysql

 

ディレクトリ

プロジェクト名が違うのはご愛敬(汗

Cargo.toml
こちらはマニフェストファイルなるもので、プロジェクトの定義やパッケージ情報、依存関係などが記載されるファイルです。

srcディレクトリ
これから開発するバイナリクレート(実行可能なバイナリを提供するためのクレート)を配置するディレクトリで拡張子は「rs」です。

1つのプロジェクトで複数のバイナリクレートを実行するには「src/bin」にバイナリクレートを配置してください。

cargo run


ルートクレートの場合の実行

cargo run --bin main


複数のバイナリクレートのうち「src/bin/main.rs」を実行する場合
 

次にmysqlのインストール

Almalinuxでは「mysql-devel」をインストールするのにリポジトリがなかったので追加します。

dnf update
rpm -Uvh https://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm
rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
dnf install -y mysql-devel

rustにORMのdieselをインストールします。

cargo install diesel_cli --no-default-features --features mysql

envファイルにDBのアクセス情報を定義してマイグレーションファイルを作成します。

.env

DATABASE_URL=mysql://[ユーザー名]:[パスワード]@[IPアドレス]/[データベース名]

 

diesel setup
diesel migration generate rust_mysql_init

作成されたマイグレーションファイルにCreateとDropをそれぞれ記述します。

Create

CREATE TABLE users
(
    id SERIAL PRIMARY KEY,
    name VARCHAR(64) NOT NULL
);

 

Drop

DROP TABLE users;

ではマイグレーションを実行します。

diesel migration run
 

今回、schema.rsの中身はこうなりました。


table! {
    users (id) {
        id -> Unsigned<Bigint>,
        name -> Varchar,
    }
}
 

で、元々プロジェクトで運用している開発環境のデータベースを参照しようしてエラーが出まくってました。

その時にはマイグレーション実行していないのでschema.rsはありませんでした。

おそらくそこがエラーの原因の大きなところだったようで定義系はすべて統一しなければならかったのですが、schema.rsなんてファイルなかったのでドはまりしていました。

 

続きます。

Cargo.toml に下記を追記します。


[dependencies]
diesel = { version = "1.4.4", features = ["mysql"] }
dotenv = "0.15.0"

 

ビルドします。

cargo build

あとはそれぞれコネクションファイル(lib.rs)モデルファイル(models.rs)、登録用ファイル(bin/insert_user.rs)、参照用ファイル(bin/show_user.rs)を作成していきます。

lib.rs

#[macro_use]
extern crate diesel;

pub mod models;
pub mod schema;
pub mod utils;


utils.rs
use diesel::mysql::MysqlConnection;
use diesel::prelude::*;
use dotenv::dotenv;
use std::env;

pub fn establish_connection() -> MysqlConnection {
    dotenv().ok();

    let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
    MysqlConnection::establish(&database_url)
        .expect(&format!("Error connecting to {}", database_url))
}


models.rs

use crate::schema::users;

#[derive(Insertable)]
#[table_name = "users"]
pub struct NewUser {
    pub name: String,
}
#[derive(Debug, Queryable)]
pub struct User {
    pub id: u64,
    pub name: String,
}

bin/insert_user.rs

use diesel::prelude::*;
use rust_mysql::models::NewUser;
use rust_mysql::schema::users as users_schema;
use rust_mysql::utils::establish_connection;

fn main() {
    let connection = establish_connection();
    let new_user = NewUser {
        name: String::from("new_user"),
    };
    diesel::insert_into(users_schema::dsl::users)
        .values(new_user)
        .execute(&connection)
        .expect("Error saving new user");
}

インサート実行 

cargo run --bin insert_user
   Compiling rust_mysql v0.1.0 (/var/www/html/sanyodo/code/rust_mysql)
    Finished dev [unoptimized + debuginfo] target(s) in 0.64s
     Running `target/debug/insert_user`


bin/show_user.rs

use diesel::prelude::*;
use rust_mysql::models::User;
use rust_mysql::schema::users as users_schema;
use rust_mysql::utils::establish_connection;

fn main() {
    let connection = establish_connection();
    let user = users_schema::dsl::users
        .first::<User>(&connection)
        .expect("Error loading users");

    println!("{:?}", user)
}

 

セレクト実行

cargo run --bin show_user

 

この程度なら結構記事があるので記載の詳細は調べてもらえればと思います。

(ほんとは細かく書きたかったのですが、諸事情により時間がなくなり書けなくなりました。気が向いたら追記するかもしれません。すみません。。。。)

DBのテーブル名やカラムの定義系は統一するのはもちろんですが、
何気にプロジェクト名をuseで使用していたのも最初気が付きませんでした。

あと、rustのエラーではあまりわかりませんでした。
結局DBからすべて記事通りに作成したらちゃんとうまくいきました。
「おごれるもの久しからず」ではないですが、まあ最初はしらんのやからちゃんと指示通りやれよっと肝に銘じました。

 

ほんとはほんとは、既存プロジェクトでいろんなテーブルからデータとってきてうん十万件のcsvファイルを作成するバッチが遅いのでそれをrustで書いたら早くならんかなと始めたのですが、初期の初歩でつまずき泥沼にはまってしまったのでタイムアップとなりました。

とりあえず、

明日頑張る!!

記事一覧へ戻る