読者です 読者をやめる 読者になる 読者になる

go言語の指针 & *

Go语言保留着C中值和指针的区别,但是对于指针繁琐用法进行了大量的简化,引入引用的概念。所以在Go语言中,你几乎不用担心会因为直接操作内寸而引起各式各样的错误。Go语言的指针,基本上只剩下用于区分 byref 和 byval 语义。

运算符就是简单的 & 和 * 一个取地址、一个解析地址。

 
package main
 
import(
    "fmt"
)
 
func main(){
    var i int // i 的类型是int型
    i=1 // i 的值为 1;
    var p *int // p 的类型是[int型的指针]
    p=&i         // p 的值为 [i的地址]
 
    fmt.Printf("i=%d;p=%d;*p=%d\n",i,p,*p)
 
    *p=2 // *p 的值为 [[i的地址]的指针] (其实就是i嘛),这行代码也就等价于 i = 2
    fmt.Printf("i=%d;p=%d;*p=%d\n",i,p,*p)
 
    i=3 // 验证想法
    fmt.Printf("i=%d;p=%d;*p=%d\n",i,p,*p)
}
这段代码执行结果:

i=1;p=0x4212f100;*p=1

i=2;p=0x4212f100;*p=2

i=3;p=0x4212f100;*p=3

函数的参数传递可以看下面例子:
 
package main
 
import "fmt"
 
type abc struct{
    v int
}
 
func (a abc)aaaa(){ //传入的是值,而不是引用
    a.v=1
    fmt.Printf("1:%d\n",a.v)
}
 
func (a *abc)bbbb(){ //传入的是引用,而不是值
    fmt.Printf("2:%d\n",a.v)
    a.v=2
    fmt.Printf("3:%d\n",a.v)
}
 
func (a *abc)cccc(){ //传入的是引用,而不是值
    fmt.Printf("4:%d\n",a.v)
}
 
func main(){
    aobj:=abc{}  //new(abc);
    aobj.aaaa()
    aobj.bbbb()
    aobj.cccc()
}
输出结果:
 

1:1

2:0

3:2

4:2

传值与传指针
当我们传一个参数值到被调用函数里面时,实际上是传了这个值的一份copy,当在被调用函数中修改参数值的时候,调用函数中相应实参不会发生任何变化,因为数值变化只作用在copy上。

传指针比较轻量级 (8bytes),只是传内存地址,我们可以用指针传递体积大的结构体。如果用参数值传递的话, 在每次copy上面就会花费相对较多的系统开销(内存和时间)。所以当你要传递大的结构体的时候,用指针是一个明智的选择。

Go语言中string,slice,map这三种类型的实现机制类似指针,所以可以直接传递,而不用取地址后传递指针。(注:若函数需改变slice的长度,则仍需要取地址传递指针)

要访问指针 p 指向的结构体中某个元素 x,不需要显式地使用 * 运算,可以直接 p.x ;

 

一个稍微复杂的例子
 
package main
 
import "fmt"
 
type S map[string][]string
 
func Summary(paramstring)(s*S){
    s=&S{
        "name":[]string{param},
        "profession":[]string{"Javaprogrammer","ProjectManager"},
        "interest(lang)":[]string{"Clojure","Python","Go"},
        "focus(project)":[]string{"UE","AgileMethodology","SoftwareEngineering"},
        "hobby(life)":[]string{"Basketball","Movies","Travel"},
    }
    return s
}
 
func main(){
    s:=Summary("Harry")
    fmt.Printf("Summary(address):%v\r\n",s)
    fmt.Printf("Summary(content):%v\r\n",*s)
}
 
 
输出:
Summary(address): 0x42131100

Summary(content): map[profession:[Java programmer Project Manager] interest(lang):[Clojure Python Go] hobby(life):[Basketball Movies Travel] name:[Harry] focus(project):[UE Agile Methodology Software Engineering]]

exit code 0, process exited normally.


 

参考资料:

使用Go语言一段时间的感受
http://blog.jobbole.com/14386/

[Go 语言] 指针,地址,形参,实参
http://my.oschina.net/nalan/blog/77373

从例子中学习 go 语言 —— 数据结构、指针
http://ilovers.sinaapp.com/drupal/node/33

Google App EngineにGoのWebAppをデプロイするために、いろいろ調査

Users API

Users Go API Overview  |  App Engine standard environment for Go  |  Google Cloud Platform

Users APIで何ができる?

  • ログイン中のuserを確認する
  • 認証用のページへユーザを誘導。(redirect)
  • Googleアカウントを持ってないユーザに新しいアカウントを作ってもらったり。

ユーザ認証

認証済の場合、ログアウト用のURLを取得し、ページに表示させる。 未認証の場合、ログイン用のURLを取得し、ページに表示させる。

import (
        "fmt"
        "net/http"

        "google.golang.org/appengine"
        "google.golang.org/appengine/user"
)

func welcome(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-type", "text/html; charset=utf-8")
        ctx := appengine.NewContext(r)
        u := user.Current(ctx)
        if u == nil {
                url, _ := user.LoginURL(ctx, "/")
                fmt.Fprintf(w, `<a href="%s">Sign in or register</a>`, url)
                return
        }
        url, _ := user.LogoutURL(ctx, "/")
        fmt.Fprintf(w, `Welcome, %s! (<a href="%s">sign out</a>)`, u, url)
}

管理者としての登録を強制させる

登録必須のページが存在する場合、app.yamlを利用して、ユーザに強制登録してもらうことが可能。
必要なロールなどを設定に任せば、認証メカニズムを独自に実装しなて済む。
詳細はyamlの設定を参照。

app.yaml Reference  |  App Engine standard environment for Go  |  Google Cloud Platform

OAuthの利用

標準ユーザ認証以外に、OAuthを利用することも可能。
※OAuthは認証プロトコルで、ユーザは第三者(アプリケーション)に許可を与えることで第三者がユーザの情報にアクセスできる。

import (
        "fmt"
        "net/http"

        "google.golang.org/appengine"
        "google.golang.org/appengine/user"
)

func welcomeOAuth(w http.ResponseWriter, r *http.Request) {
        ctx := appengine.NewContext(r)
        u, err := user.CurrentOAuth(ctx, "")
        if err != nil {
                http.Error(w, "OAuth Authorization header required", http.StatusUnauthorized)
                return
        }
        if !u.Admin {
                http.Error(w, "Admin login only", http.StatusUnauthorized)
                return
        }
        fmt.Fprintf(w, `Welcome, admin user %s!`, u)
}

認証のoptions

認証方法を選択することも可能。(設定変更することで)以下の方法がある。

Googleアカウントと開発サーバー

開発サーバーのシミュレーターはダミーの認証を提供する。これを利用すればユーザ認証、管理者認証のテストが容易にできる。

Android GridViewのItemの背景を変える

簡単かと思ったが、やってみたらけっこうはまった。

やり方

ArryAdapterにitemのlayoutを設定、itemのbackgroundにtextViewの背景を変更するselectorを設定。

ハマったところ

selected状態に色を変えたくて、android:state_selectedを設定してもぜんぜん効かない。 なんと、android:state_activatedに変えたらいけた。

ソース

ArrayAdapter<RoomBean> adapter = new ArrayAdapter<>(getApplicationContext(), R.layout.grid_room_item, result);
                gridView.setAdapter(adapter);
                gridView.setChoiceMode(GridView.CHOICE_MODE_SINGLE);
                gridView.setItemChecked(0, true);
<GridView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="0.17"
            android:id="@+id/gridViewRoom"
            android:numColumns="3"
            android:layout_marginTop="10dp"
            android:verticalSpacing="10dp"
            android:horizontalSpacing="10dp"
            android:padding="10dp"
            android:background="#999999"
            android:listSelector="@android:drawable/list_selector_background">
        </GridView>
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/textView1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:textSize="30sp"
    android:padding="20dp"
    android:background="@drawable/item_room_selector"
    android:text="TextView" />
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:state_activated="true" >
        <shape android:shape="rectangle">
            <solid
                android:color="@color/LightBlue"
                />
        </shape>
    </item>
    <item
        android:state_pressed="true" >
        <shape android:shape="rectangle">
            <solid
                android:color="@color/LightBlue"
                />
        </shape>
    </item>
    <item>
        <shape android:shape="rectangle">
            <solid
                android:color="@color/White"
                />
        </shape>
    </item>

</selector>

LinearLayoutの中のボタンをbottomに表示させる

androidのlayoutを理解してないまま、gravityとかでやってみたが、 だめだった。

結局、開けたいスペースにSpaceを入れて高さがいっぱいまで設定したらうまくいった。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!-- Other views -->
    <Space
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

    <!-- Target view below -->
    <View
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

</LinearLayout>

aws elasticbeanstalk でデプロイをする

[AWS] [AWS Elastic Beanstalk] AWS Elastic Beanstalk のデプロイ環境と基礎知識 | UI/UX Design、フロントエンド系の技術に関する備忘録 | whiskers

上記を参考。

仕事で既に用意されたAWS Elastic Beanstalk 環境にデプロイする機会があったので環境構築と使い方についてメモしておきます。AWSやGitについては説明を省くのでこれから使い始めたい方は以下のページを参考にどうぞ。

1, AWS Elastic Beanstalk とは

AWS Elastic Beanstalk は、Java、.NET、PHP、Node.js、PythonRuby、Go および Docker を使用して開発されたウェブアプリケーションやサービスを、Apache、Nginx、Passenger、IIS など使い慣れたサーバーでデプロイおよびスケーリングするための、使いやすいサービスです。

お客様はコードをアップロードするだけで、Elastic Beanstalk が、キャパシティのプロビジョニング、ロードバランシング、Auto Scaling からアプリケーションの状態モニタリングまで、デプロイを自動的に処理します。同時に、お客様のアプリケーションが稼動している AWS リソースの完全なコントロールを維持でき、いつでも基本的なリソースにアクセスすることができます。

AWS Elastic Beanstalk

もう少し具体的に言うとgitのリポジトリAWS Elastic BeanstalkにpushしてAWS環境に自動デプロイしてくれるサービスです。デザイナーやフロントエンジニアは既に用意されたAWS Elastic Beanstalk環境にpushするだけでデプロイを行うことができます。

2, デザイナーやフロントエンジニアがAWS Elastic Beanstalkを使うには

AWS Elastic Beanstalkを使うために必要なソフトウェアは以下の通り。

2.1, IAMアカウント

Gitは既に使っている前提で、デザイナーやフロントエンジニアであればインフラエンジニアからIAMアカウントが発行されるはずです。発行されたIAMアカウントでAWSマネジメントコンソールにアクセスし、アクセスキーとシークレットキーをメモしておきます。

このアクセスキーとシークレットキーをユーザーrootの.aws/credentialsAWSへアクセスするためのプロファイル<profile-name>を定義します。<profile-name>の部分は任意の指定が可能です。

[<profile-name>]
aws_access_key_id = <AWS_ACCESS_KEY_ID>
aws_secret_access_key = <AWS_SECRET_ACCESS_KEY>

2.2, Python

詳しいインストール方法は記載しませんがHomebrewからインストール可能です。インストールが完了したらバージョンを確認しておきます。

$ brew install python
$ python -V
Python 2.7.9

2.3, Elastic Beanstalk CLI

AWS Elastic Beanstalkをコマンドラインから操作するためにElastic Beanstalk CLIをHomebrew経由でインストールします。インストールが完了したらこちらもバージョンを確認します。

$ brew install aws-elasticbeanstalk
$ eb --version
EB CLI 3.3.2 (Python 2.7.6)

これでAWS Elastic Beanstalkに必要な環境は用意できました。

3, デプロイするための準備

インフラエンジニアがすでに環境を用意している前提でデプロイするための準備を行います。AWS Elastic Beanstalkにデプロイするためにはまずgitプロジェクトを定義します。

$ mkdir <project_directory>
$ cd <project_directory>
$ git init

3.1, AWS Elastic Beanstalk

次に$ eb init --profile <profile-name>を実行し質問形式でElastic Beanstalkプロジェクトを設定していきます。<profile-name>はIAMアカウントを設定した際に.aws/credentialsに記載したプロファイルネームです。質問は以下の3つになります。

  1. リージョン(AWSのリージョン)
  2. アプリケーション(用意されているアプリケーション)
  3. 環境(テスト、本番等)

アプリケーションと環境はインフラエンジニアが用意しているはずなので、基本的に番号を入力して選択していくだけです。リージョンについてはマネジメントコンソールから確認が必要ですが、日本であればTokyoになるでしょう。コマンドが完了すると.elasticbeanstalk/config.yml.gitignoreが作られます。

.elasticbeanstalk/config.ymlにはgitのブランチmaster:に合わせて環境名environment: app-prdが指定されます。masterブランチでデプロイを実行した際、app-prdの環境にデプロイするという指定です。

branch-defaults:
  master:
    environment: app-prd
global:
  application_name: appname
  default_ec2_keyname: hoge-fuga
  default_platform: 64bit Amazon Linux 2015.03 v1.3.2 running PHP 5.6
  default_region: ap-northeast-1
  profile: <profile-name>
  sc: git

.gitignoreの中身はこのようになっています。

# Elastic Beanstalk Files
.elasticbeanstalk/*
!.elasticbeanstalk/*.cfg.yml
!.elasticbeanstalk/*.global.yml

これでデプロイの準備が完了しました。あとは$ git add ...$ git commit ...してコミットしておきます。

4, AWS Elastic Beanstalkにデプロイする

デプロイ作業は簡単、コマンド1発です。コマンドを実行するとインフラエンジニアの手を煩わせず自動でデプロイ処理が行われます。

$ eb deploy

デプロイ先を確認するのもコマンドから行えます。ブラウザが起動しデプロイ先が表示されます。

$ eb open

4.1, developブランチをテスト環境にデプロイするには

developブランチの場合はテスト環境にデプロイしたい、そんな時はdevelopブランチにcheckoutし$ eb initを行うことでブランチ設定を追加することができます。

branch-defaults:
  master:
    environment: app-prd
  develop:
    environment: app-dev
...

4.2, 環境情報を知りたい

$ eb status
Environment details for: <env-name>
  Application name: <app-name>
  Region: ap-northeast-1
  Deployed Version: fba1
  Environment ID: <id>
  Platform: 64bit Amazon Linux 2015.03 v1.3.2 running PHP 5.6
  Tier: WebServer-Standard-1.0
  CNAME: <xxxxxxx.elasticbeanstalk.com>
  Updated: 2015-05-18 11:59:23.048000+00:00
  Status: Ready
  Health: Green
Alert: An update to this CLI is available.

4.3, マネジメントコンソールを開く

$ eb console [environment_name]

4.4, アプリケーションの環境一覧を表示する

$ eb list

4.5, 環境に設定されている環境変数を表示する

$ eb printenv [environment_name]

環境変数を設定することもできます。

$ eb setenv key=[value]

4.6, デフォルトの環境を設定する

$ eb use <environment_name>

5, その他のコマンド

以下のコマンドを使う機会はそれほどないと思いますが一応紹介しておきます。

5.1, 環境を新たに作成する

$ eb create <env-name>

5.2, 実行中の環境をシャットダウンする

$ eb terminate [env-name]

5.3, アプリケーションを完全に削除する

このコマンドを実行するとアプリケーションが消えるのでかなり危険なコマンドです。

$ eb terminate --all

6, まとめ

デプロイ系のツールをはじめて使いましたが便利ですね。すべては紹介しきれていないので下記ドキュメントを改めて読むとコマンド周りを一通り覚えることができると思います。

AsyncTask 注意点

AsyncTaskを使ってUIThreadと違うThreadでsocket通信などをしたら、複数AsyncTask同時実行されない現象があった。 どうもデフォルトだとAsyncTaskが並行実行されず、順番待ちみたい。

調べたら、AsyncTaskには以下の二つの実行モードがあると分かった。

  • THREAD_POOL_EXECUTOR
    並列

  • SERIAL_EXECUTOR
    単列

Android 開発 viewをリサイズ

やり方をメモ

タイミング

Activity内なら、onWindowFocusChanged(hasFocus=true)いい。 onCreateだと、viewがまだ見えない、取得する幅が0のまま。

カスタマビューを使ってるなら、surfaceCreated(SurfaceViewの場合)でもいい。

設定の仕方

this.getLayoutParams().height = (int) height;
this.getLayoutParams().width = (int) width;