JSゆるふわめも

がっこうでべんきょうしたことをめもがきしてます

ポインタレシーバーと値レシーバー

最近Goは全く触っていないです。 ただ、寝れなくなったのでGoを学習していた時によく分かっていなかったことを少し調べてみました。

それはコイツらです。

type Person struct { Name string }

//値レシーバー
func (p Person) hello() {
  fmt.Printf("Hi, my name is %s", p.Name)
}
//ポインタレシーバー
func (p *Person) hello() {
  fmt.Printf("Hi, my name is %s", p.Name)
}

これらをどう使い分けるのか?よく分かっていませんでした。 ぶっちゃけよく分かっていなくても練習問題は解けたので気にもしてませんでした。

正直今も正しく理解できているか謎ですが、下記のブログを読んで理解したことを意識低くメモします。

skatsuta.github.io

qiita.com

値レシーバーはメソッド定義された型の値をコピーして呼び出されます。 なので、下記のようなNewNameを定義しても呼び出し元の値は変化しません。

type Person struct { Name string }

func (p Person) NewName(newName string) {
 p.Name = newName
}

func main(args string...) {
   p := Person{ Name : taro }
   p.NewName
   fmt.Printf("My name is %s", p.Name) //My name is taro
}

逆にポインタレシーバーの場合は変化します。 つまり、呼び出し元のフィールド値を書き換えたいような場合はポインタレシーバーを使用して、 呼び出し元を変化させたくない(immutable)場合は値レシーバーを使用します。

また、値レシーバーは呼び出し元を丸っとコピーするので大きな構造体に対する呼び出しは高コストになるため避けたほうが良いです。

開発環境のバージョンって大事だね

Unityをいじってて最近ブチ当たったのがバージョンの問題 dllを追加しようとしたら.NET4.xだからダメで〜す的なメッセージが表示された訳です

全く意識してなかったのですが、UnityのバージョンによってサポートしているC#, .NETのバージョンは異なる訳で...

決まり切った環境と言語だとこの辺は気にすることや対処法は染み付いているのですが、新しい環境だと何がどういうバージョンでどうなっているのか全くわからないので事前にキチンと調べておくことが大事ですね。

www.slideshare.net

C#はじめます

次の業務的でC#を読む可能性が微レ存(死後)なので、基礎を勉強しようと思う。 「Javaとほとんど同じですよ!」と言われたけど、何も知らないと細かいところは分からない。

しかし、usingはJavaのtry-with resource, Goのdefer的なやつかな?とか => ってラムダなんだろうとか過去に学んできた言語の下地がある分学習効率は上がってる気がする。

JS低学年の頃はC言語でif while プリミティブ型以上!状態だったので...

Youtubeのエラーページ

数ヶ月前にYoutubeが10分ほどダウンした時にとったスクショ

A team of highly trained monkeys has been dispatched to deal with this situation.

f:id:Qlib:20171021224752p:plain

エラーメッセージ・画面もシャレが効いてる

PS4とコントローラのペアリング不調

結論から言うと電源を一度抜いたら治りました。 完全にメモリクリアする必要があったようです。

一般的な治し方?であるセーフモードを色々いじくっても全く治らなかったので途方にくれていたのですが、治って良かったです。(Amazon Primeビデオ視聴マシンと成り下がっていますが…)

ファイナライザを避ける

ファイナライザ

GCによって、インスタンスが回収されるタイミングで実行されるメソッド

ファイナライザは(原則)使用するべきでは無い

理由

  • ファイナライザは即時実行されるわけでは無い(意図しないタイミングで実行される可能性がある)
  • そもそも実行されることが保証されていない

ファイナライザ相当のことをしたい場合

  • 明示的にコールする後処理メソッドを書く
    • terminate, dipose, etc…
  • 上記メソッドがコールされたことを管理するフィールド値をオブジェクトに持たせる
    • isTerminated, isDisposed

参考: ExecutorService (Java Platform SE 6)

ファイナライザの使い所は?

上記メソッドを呼び出し忘れた時の保険

実装する場合の注意点

親クラスでファイナライザが実装されている場合、忘れずに呼び出すこと

  • かなり簡略化しているので、正確完全な情報はEffective Java原本を参照してください

text/scanner

Package scanner provides a scanner and tokenizer for UTF-8-encoded text. It takes an io.Reader providing the source, which then can be tokenized through repeated calls to the Scan function. For compatibility with existing tools, the NUL character is not allowed. If the first character in the source is a UTF-8 encoded byte order mark (BOM), it is discarded.

By default, a Scanner skips white space and Go comments and recognizes all literals as defined by the Go language specification. It may be customized to recognize only a subset of those literals and to recognize different identifier and white space characters.

スキャナパッケージはUTF-8エンコーディングされたテキストを対象にしたscannerとtokenizerを持っている。Scanメソッドを繰り返し呼び出すことで、ソースコードが記述されたio.Readerをtokenizedできる。既存のツールとの互換性を維持するために、ヌル文字は使用することができない。もしソースコードの先頭にBOMが付いていても無視される。

基本的にScannerは空白文字とコメントは読み飛ばし、Go言語仕様で定義された全てのリテラル値をパースする。しかし、scannerは異なるルールのソースコードをパースするためにカスタマイズされている場合もある。

サンプル

import (
    "fmt"
    "strings"
    "text/scanner"
)

func main() {
    const c = `
// This is scanned code.
var i int
var s string = "text"
if a > 10 {
    someParsable = text
}`
    var s scanner.Scanner
    s.Init(strings.NewReader(c))
    s.Filename = "test"
    for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
        fmt.Printf("%s:%v %v\n", s.Position, scanner.TokenString(tok), s.TokenText())
    }
}

実行結果

test:3:1:Ident var
test:3:5:Ident i
test:3:7:Ident int
test:4:1:Ident var
test:4:5:Ident s
test:4:7:Ident string
test:4:14:"=" =
test:4:16:String "text"
test:5:1:Ident if
test:5:4:Ident a
test:5:6:">" >
test:5:8:Int 10
test:5:11:"{" {
test:6:2:Ident someParsable
test:6:15:"=" =
test:6:17:Ident text
test:7:1:"}" }

Scanメソッドの返り値は

  • リテラル値は型
  • 変数・関数名(上記以外のもの)はIdent
  • { ( などはそのまま