Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The First Step for Building Groonga Bindings with Golang

The First Step for Building Groonga Bindings with Golang

Goで体験
はじめての
Groonga bindingづくり

全文検索エンジンGroonga勉強会@札幌
2014-03-29 札幌市民ホール 第4会議室

Yoji Shidara

March 29, 2014
Tweet

More Decks by Yoji Shidara

Other Decks in Technology

Transcript

  1. ͸͡Ίͯͷ

    (SPPOHBCJOEJOHͮ͘Γ
    ઃᒜ༸࣐

    !EBSBTIJ
    (PͰମݧ
    5IFNBTDPUXBTEFTJHOFECZ3FOÉF'SFODI

    -JDFOTFEVOEFS$$#:
    શจݕࡧΤϯδϯ(SPPOHBษڧձˏࡳຈ

    ࡳຈࢢຽϗʔϧୈձٞࣨ
    — The First Step for Building Groonga Bindings with Golang

    View full-size slide

  2. 5IFNBTDPUXBTEFTJHOFECZ3FOÉF'SFODI

    -JDFOTFEVOEFS$$#:

    View full-size slide

  3. 8IZ(P
    w DHPΛ࢖͏ͱ$ͷίʔυΛखܰʹݺ΂Δ
    w HPSVOͰ͘͘͞͞ࢼͤΔ
    w ָ͍͠ ࣗ෼͕

    View full-size slide

  4. (Pʔϧ
    (P͔Β(SPPOHBΛ৮ΔϥΠϒϥϦΛ࡞Δ

    View full-size slide

  5. (Pʔϧ
    (P͔Β(SPPOHBΛ৮ΔϥΠϒϥϦΛ࡞Δ

    ʜͨΊͷୈҰาΛ౿Έग़͢

    View full-size slide

  6. ΍Βͳ͍͜ͱ
    w ϥΠϒϥϦͱͯ͠៉ྷʹ੔͑Δ
    w େ൒ͷΤϥʔॲཧ
    w ΫΤϦʔݴޠΛհ͞ͳ͍

    ௿Ϩϕϧͳ(SPPOHB"1*ͷར༻

    View full-size slide

  7. Groonga2013 Powered by Rabbit 2.1.2
    Groonga
    libgroonga
    gqtp
    _
    `a bcd e
    fBg
    e
    fh
    Bij

    kQ
    groonga
    l
    API
    HTTP
    SQL
    CLI
    ,PIFJ4VUP l(SPPOHB଒zIUUQTMJEFSBCCJUTIPDLFSPSHBVUIPSTLPVHSPPOHBOJHIU$$#:4"

    View full-size slide

  8. Groonga2013 Powered by Rabbit 2.1.2
    Groonga
    libgroonga
    gqtp
    _
    `a bcd e
    fBg
    e
    fh
    Bij

    kQ
    groonga
    l
    API
    HTTP
    SQL
    CLI
    ,PIFJ4VUP l(SPPOHB଒zIUUQTMJEFSBCCJUTIPDLFSPSHBVUIPSTLPVHSPPOHBOJHIU$$#:4"
    ͔͜͜Β

    ࢖͏

    View full-size slide

  9. HSPPOHBίϚϯυ

    View full-size slide

  10. $ groonga

    > status
    [[0,1395981744.74587,3.814697265625e-05],
    {"alloc_count":151,"starttime":
    1395981645,"uptime":
    99,"version":"4.0.0","n_queries":
    0,"cache_hit_rate":0.0,"command_version":
    1,"default_command_version":
    1,"max_command_version":2}]

    View full-size slide

  11. Groonga2013 Powered by Rabbit 2.1.2
    Groonga
    libgroonga
    gqtp
    _
    `a bcd e
    fBg
    e
    fh
    Bij

    kQ
    groonga
    l
    API
    HTTP
    SQL
    CLI
    ,PIFJ4VUP l(SPPOHB଒zIUUQTMJEFSBCCJUTIPDLFSPSHBVUIPSTLPVHSPPOHBOJHIU$$#:4"
    ࠓͷ͸

    $-*

    View full-size slide

  12. ͜Θ͘ͳ͍
    w ࢝·ΓͱऴΘΓ

    HSO@JOJU
    HSO@pO

    w ίϯςΩετ HSO@DUY
    ͷ࡞੒ͱഁغ

    HSO@DUY@JOJU
    HSO@DUY@pO

    w σʔλϕʔεͷ࡞੒ɾΦʔϓϯͱΫϩʔζ

    HSO@EC@DSFBUF
    HSO@EC@PQFO
    HSO@PCK@DMPTF

    w ίϚϯυͷૹ৴ͱड৴

    HSO@DUY@TFOE
    HSO@DUY@SFDW

    View full-size slide

  13. ͸͡ΊͷҰา

    View full-size slide

  14. લఏ
    w (P͕Πϯετʔϧ͞Ε͍ͯΔ
    w (SPPOHB͕Πϯετʔϧ͞Ε͍ͯΔ
    w QLHDPOpH͕(SPPOHBΛݟ͚ͭΒΕΔ

    View full-size slide

  15. package main
    !
    /*
    #cgo pkg-config: groonga
    #include
    */
    import "C"
    !
    func main() {
    }

    View full-size slide

  16. $ go run main.go
    $
    ʮԿ΋͠ͳ͍ʯΛͨ͠

    View full-size slide

  17. (SPPOHBϥΠϒϥϦͷ

    ॳظԽͱ։์

    View full-size slide

  18. '
    '
    (
    (
    )
    )
    *
    *
    #
    #
    ,
    , file
    file 349 lines (221 sloc)
    349 lines (221 sloc) 12.16 kb
    12.16 kb
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    =,groonga,C,API,ϚχϡΞϧ
    groongaͷCݴޠAPI͸ɺ1)ڞ௨APIɺ2)QL,APIɺ3)DB,APIɺ4)௿ϨϕϧAPIͷ4छʹେผ͞ΕΔɻ
    ڞ௨API͸ଞͷશͯͷAPIͱ૊Έ߹Θͤͯڞ௨ʹ࢖༻͞ΕΔɻ࢒Γͷ3छͷAPI͸֊૚ߏ଄Λͳ͍ͯ͠Δɻ
    QL,API͸࠷΋্ҐʹҐஔ͠ɺquery,languageΛհͯ͠σʔλετΞΛૢ࡞͢ΔػೳΛఏڙ͢Δɻ
    DB,API͸QL,APIͷԼҐʹҐஔ͠ɺσʔλετΞΛߏ੒͢Δ֤ΦϒδΣΫτΛૢ࡞͢ΔػೳΛఏڙ͢Δɻ
    ௿ϨϕϧAPI͸DB,APIͷ͞ΒʹԼҐʹҐஔ͠ɺσʔλΦϒδΣΫτͷߏ੒ཁૉΛ௚઀ૢ࡞͢ΔػೳΛఏڙ͢Δɻ
    =,ڞ௨API
    ==,grn_init
    :NAME
    ,,grn_init,,grn_fin,I,groongaϥΠϒϥϦΛॳظԽ/ղ์͢Δ
    :SYNOPSIS
    ,((','))
    ,,#include,
    ,,grn_rc,grn_init(void);
    ,,grn_rc,grn_fin(void);
    :DESCRIPTION
    ,,grn_init()͸ɺlibgroonga͕ඞཁͱ͢ΔࢿݯͷॳظԽΛߦ͏ɻlibgroongaΛ࢖༻͢ΔϓϩάϥϜ͸ଞͷgroonga,APIؔ਺Λݺͼग़͢લʹҰ౓͚ͩgrn_init()Λݺͼग़͞ͳ͚
    ,,grn_fin()͸libgroonga͕࢖༻͢ΔࢿݯΛղ์͢Δɻgrn_fin()࣮ߦޙʹgroonga,APIؔ਺Λ࣮ߦͯ͠͸ͳΒͳ͍ɻ
    :RETURN,VALUE
    ,,੒ޭͨ͠৔߹͸GRN_SUCCESSΛฦ͢ɻ
    ,,grn_init()͸ɺࢿݯͷ֬อʹࣦഊͨ͠৔߹ʹGRN_NO_MEMORY_AVAILABLEΛฦ͢ɻ
    :NOTES
    ,,grn_init(),,grn_fin()͸ϦΤϯτϥϯτͰ͸ͳ͍ɻͦͷଞͷgroongaͷC,APIؔ਺͸શͯϦΤϯτϥϯτͰ͋Δɻ
    -
    -
    - Open
    Open
    Open Edit
    Edit
    Edit Raw
    Raw Blame
    Blame History
    History Delete
    Delete
    IUUQTHJUIVCDPNHSPPOHBHSPPOHBCMPCNBTUFSEPD"1*SE

    View full-size slide

  19. package main
    !
    /*
    #cgo pkg-config: groonga
    #include
    */
    import "C"
    !
    func main() {
    C.grn_init() // TODO error handling
    defer C.grn_fin() // TODO error handling
    }
    NBJO
    ͕ऴΘΔͱ͖ʹ࣮ߦ͢Δ

    View full-size slide

  20. ίϯςΩετͷ

    ࡞੒ͱഁغ

    View full-size slide

  21. ʜίϯςΩετͬͯԿ

    View full-size slide

  22. IUUQHSPPOHBPSHKBEPDTSFGFSFODFBQJHSO@DUYIUNM

    View full-size slide

  23. 39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    ==,grn_ctx_init
    :NAME
    ,,grn_ctx_init,,grn_ctx_fin,I,grn_ctxߏ଄ମΛॳظԽ/ղ์͢Δ
    :SYNOPSIS
    ,((','))
    ,,#include,
    ,,grn_rc,grn_ctx_init(grn_ctx,*ctx,,int,flags,,grn_encoding,encoding);
    ,,grn_rc,grn_ctx_fin(grn_ctx,*ctx);
    :DESCRIPTION
    ,,grn_ctx͸ɺ1)Τϥʔ৘ใͷ௨஌ɺ2)API಺෦Ͱ࢖༻͢ΔϝϞϦͷ؅ཧɺ3)ΫΤϦݴޠॲཧܥͷ؅ཧͷͨΊʹ࢖༻͞ΕΔߏ଄ମͰ͋Δɻ΄ͱΜͲͷAPIؔ਺͸ୈҰҾ਺ʹgrn_ct
    ,,,typedef,struct,_grn_ctx,grn_ctx;
    ,,,struct,_grn_ctx,{
    ,,,,,grn_rc,rc;,,,,,,,,,,,,,,,,,,,,,,,/*,࠷ޙʹ࣮ߦͨ͠APIͷऴྃίʔυ,*/
    ,,,,,int,flags;,,,,,,,,,,,,,,,,,,,,,,,/*,಺෦ॲཧ༻,*/
    ,,,,,grn_encoding,encoding;,,,,,,,,,,,/*,σϑΥϧτͷจࣈΤϯίʔσΟϯά,*/
    ,,,,,unsigned,char,ntrace;,,,,,,,,,,,,/*,όοΫτϨʔεͷ਺,*/
    ,,,,,unsigned,char,errlvl;,,,,,,,,,,,,/*,࠷ޙʹൃੜͨ͠ΤϥʔͷϨϕϧ,*/
    ,,,,,unsigned,char,stat;,,,,,,,,,,,,,,/*,಺෦ॲཧ༻,*/
    ,,,,,unsigned,int,seqno;,,,,,,,,,,,,,,/*,಺෦ॲཧ༻,*/
    ,,,,,unsigned,int,subno;,,,,,,,,,,,,,,/*,಺෦ॲཧ༻,*/
    ,,,,,unsigned,int,seqno2;,,,,,,,,,,,,,/*,಺෦ॲཧ༻,*/
    ,,,,,unsigned,int,errline;,,,,,,,,,,,,/*,Τϥʔ͕ൃੜͨ͠Օॴͷߦ൪߸,*/
    ,,,,,grn_ctx,*prev;,,,,,,,,,,,,,,,,,,,/*,಺෦ॲཧ༻,*/
    ,,,,,grn_ctx,*next;,,,,,,,,,,,,,,,,,,,/*,಺෦ॲཧ༻,*/
    ,,,,,const,char,*errfile;,,,,,,,,,,,,,/*,Τϥʔ͕ൃੜͨ͠ιʔεϑΝΠϧ໊,*/
    ,,,,,const,char,*errfunc;,,,,,,,,,,,,,/*,Τϥʔ͕ൃੜͨؔ͠਺໊,*/
    ,,,,,struct,_grn_ctx_impl,*impl;,,,,,,/*,಺෦ॲཧ༻,*/
    ,,,,,void,*trace[16];,,,,,,,,,,,,,,,,,/*,όοΫτϨʔεϙΠϯλ഑ྻ,*/
    ,,,,,char,errbuf[GRN_CTX_MSGSIZE];,,,,/*,࠷ޙʹൃੜͨ͠Τϥʔʹؔ͢Δϝοηʔδ,*/
    ,,,};
    ,,grn_ctxߏ଄ମ͸APIͰ࢖༻͢Δલʹgrn_ctx_init()ͰॳظԽ͠ͳ͚Ε͹ͳΒͳ͍ɻॳظԽ͢Δgrn_ctxߏ଄ମ΁ͷϙΠϯλΛ'ctx'ʹࢦఆ͢Δɻ'flags'ʹGRN_CTX_USE_QL
    IUUQTHJUIVCDPNHSPPOHBHSPPOHBCMPCNBTUFSEPD"1*SE

    View full-size slide

  24. IUUQHSPPOHBPSHKBEPDTSFGFSFODFBQJHSO@DUYIUNM
    ͬͪ͜Λ࢖ͬͯΈ·͢
    HSO@DUY@JOJUͰ͸ͳ͘

    View full-size slide

  25. package main
    !
    /*
    #cgo pkg-config: groonga
    #include
    #include
    */
    import "C"
    !
    func main() {
    C.grn_init() // TODO error handling
    defer C.grn_fin() // TODO error handling
    !
    ctx := C.grn_ctx_open(0)
    defer C.grn_ctx_fin(ctx) // TODO error handling
    }
    qBHT͸ͱΓ͋͑ͣͰ

    View full-size slide

  26. σʔλϕʔεΛ

    ͭ͘Δɾͱ͡Δ

    View full-size slide

  27. It is used for specifying options for grn_db_create().
    char **grn_db_create_optarg.builtin_type_names
    ૊ΈࠐΈܕͷ໊લͱͳΔnulऴ୺จࣈྻͷ഑ྻΛࢦఆ͢Δɻ
    int grn_db_create_optarg.n_builtin_type_names
    n_builtin_type_namesʹ͸ɺoptarg.builtin_type_namesͰࢦఆ͢Δจࣈྻͷ਺Λ ࢦఆ͢Δɻ഑
    ྻͷoffset͸enumܕgrn_builtin_typeͷ஋ʹରԠ͢Δɻ
    grn_obj *grn_db_create(grn_ctx *ctx, const char *path, grn_db_create_optarg *optarg)
    ৽ͨͳdbΛ࡞੒͠·͢ɻ
    ύ
    ϥ
    ϝ
    λ:
    ctx -- ॳظԽࡁΈͷ grn_ctx Λࢦఆ͠·͢ɻ
    path -- ࡞੒͢ΔdbΛ֨ೲ͢ΔϑΝΠϧύεΛࢦఆ͠·͢ɻNULLͳΒtemporary db
    ͱͳΓ·͢ɻNULLҎ֎ͷύεΛࢦఆͨ͠৔߹͸persistent dbͱͳΓ·͢ɻ
    optarg --
    Currently, it is not used. It is just ignored.
    ࡞੒͢Δdbͷ૊ΈࠐΈܕͷ໊લΛมߋ͢Δ࣌ʹࢦఆ͠·͢ɻ
    optarg.builtin_type_namesʹ͸ɺ૊ΈࠐΈܕͷ໊લͱͳΔnullऴ୺จࣈྻͷ഑ྻΛࢦ
    ఆ͠·͢ɻoptarg.n_builtin_type_namesʹ͸ɺoptarg.builtin_type_namesͰࢦఆ͢Δจ
    ࣈྻͷ਺Λࢦఆ͠·͢ɻ഑ྻͷoffset͸enumܕgrn_builtin_typeͷ஋ʹରԠ͠·͢ɻ
    grn_obj *grn_db_open(grn_ctx *ctx, const char *path)
    طଘͷdbΛ։͖·͢ɻ
    ύϥϝλ: path -- ։͜͏ͱ͢ΔdbΛ֨ೲ͢ΔϑΝΠϧύεΛࢦఆ͠·͢ɻ
    void grn_db_touch(grn_ctx *ctx, grn_obj *db)
    dbͷ಺༰ͷ࠷ऴߋ৽࣌ࠁΛݱࡏ࣌ࠁʹ͠·͢ɻ
    ࠷ऴߋ৽࣌ࠁ͸Ωϟογϡ͕༗ޮ͔Ͳ͏͔ͷ൑அͳͲʹར༻͞Ε·͢ɻ
    ύϥϝλ: db -- ಺༰͕มߋ͞ΕͨdbΛࢦఆ͠·͢ɻ
    grn_obj *grn_obj_db(grn_ctx *ctx, grn_obj *obj)
    objͷଐ͢ΔdbΛฦ͠·͢ɻ
    ύϥϝλ: obj -- ର৅objectΛࢦఆ͠·͢ɻ
    ϞδϡʔϧɺΫϥεɺ·ͨ͸ؔ਺໊
    Λೖྗ͍ͯͩ͘͠͞
    IUUQHSPPOHBPSHKBEPDTSFGFSFODFBQJHSO@ECIUNM
    طଘͷ%#Λ։͘ͱ͖͸͜Ε
    ͜ΕΛ࢖͍·͢

    View full-size slide

  28. package main
    !
    /*
    #cgo pkg-config: groonga
    #include
    #include
    */
    import "C"
    import "unsafe"
    !
    func main() {
    C.grn_init() // TODO error handling
    defer C.grn_fin() // TODO error handling
    !
    ctx := C.grn_ctx_open(0)
    defer C.grn_ctx_fin(ctx) // TODO error handling
    !
    dbPath := "db"
    cDbPath := C.CString(dbPath)
    defer C.free(unsafe.Pointer(cDbPath))
    db := C.grn_db_create(ctx, cDbPath, nil)
    if db == nil {
    log.Fatal("[grn_db_create] Failed to create DB")
    }
    defer C.grn_obj_close(ctx, db)
    }
    EC1BUIΛ$ͷจࣈྻʹ͠·͢

    View full-size slide

  29. import "fmt"
    func main() {
    f := C.intFunc(C.fortytwo)
    fmt.Println(int(C.bridge_int_func(f)))
    // Output: 42
    }
    In C, a function argument written as a fixed size array actually requires a pointer to the first element of the array. C compilers are
    aware of this calling convention and adjust the call accordingly, but Go cannot. In Go, you must pass the pointer to the first element
    explicitly: C.f(&x[0]).
    A few special functions convert between Go and C types by making copies of the data. In pseudo-Go definitions:
    // Go string to C string
    // The C string is allocated in the C heap using malloc.
    // It is the caller's responsibility to arrange for it to be
    // freed, such as by calling C.free (be sure to include stdlib.h
    // if C.free is needed).
    func C.CString(string) *C.char
    // C string to Go string
    func C.GoString(*C.char) string
    // C string, length to Go string
    func C.GoStringN(*C.char, C.int) string
    // C pointer, length to Go []byte
    func C.GoBytes(unsafe.Pointer, C.int) []byte
    C references to Go
    Go functions can be exported for use by C code in the following way:
    //export MyFunction
    func MyFunction(arg1, arg2 int, arg3 string) int64 {...}
    //export MyFunction2
    func MyFunction2(arg1, arg2 int, arg3 string) (int64, *C.char) {...} IUUQHPMBOHPSHDNEDHP

    View full-size slide

  30. 265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    ==,grn_ctx_send
    :NAME
    ,,grn_ctx_send,I,͓͘Δ
    :SYNOPSIS
    ,((','))
    ,,#include,
    ,,unsigned,grn_ctx_send(grn_ctx,*ctx,,char,*str,,unsigned,int,str_len,,int,flags);
    :DESCRIPTION
    ,,͓͘Δ
    ==,grn_ctx_recv
    :NAME
    ,,grn_ctx_recv,I,͏͚ͱΔ
    :SYNOPSIS
    ,((','))
    ,,#include,
    ,,unsigned,grn_ctx_recv(grn_ctx,*ctx,,char,**str,,unsigned,int,*str_len,,int,*flags);
    :DESCRIPTION
    ,,͏͚ͱΔ
    =,DB,API
    ==,grn_db_create
    :NAME
    ,,grn_db_create,,grn_db_open,I,σʔλϕʔεΛੜ੒͢Δ
    IUUQTHJUIVCDPNHSPPOHBHSPPOHBCMPCNBTUFSEPD"1*SE

    View full-size slide

  31. package main
    !
    /*
    #cgo pkg-config: groonga
    #include
    #include
    */
    import "C"
    import "unsafe"
    !
    func main() {
    C.grn_init() // TODO error handling
    defer C.grn_fin() // TODO error handling
    !
    ctx := C.grn_ctx_open(0)
    defer C.grn_ctx_fin(ctx) // TODO error handling
    !
    dbPath := "db"
    cDbPath := C.CString(dbPath)
    defer C.free(unsafe.Pointer(cDbPath))
    db := C.grn_db_create(ctx, cDbPath, nil)
    if db == nil {
    log.Fatal("[grn_db_create] Failed to create DB")
    }
    defer C.grn_obj_close(ctx, db)
    !
    command := "status"
    cCommand := C.CString(command)
    defer C.free(unsafe.Pointer(cCommand))
    C.grn_ctx_send(ctx, cCommand, C.uint(len(command)), 0) // TODO error handling
    }
    DPNNBOEΛ$ͷจࣈྻʹ͠·͢
    ίϚϯυ௕ qBHT͸ͱΓ͋͑ͣͰ

    View full-size slide

  32. 265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    ==,grn_ctx_send
    :NAME
    ,,grn_ctx_send,I,͓͘Δ
    :SYNOPSIS
    ,((','))
    ,,#include,
    ,,unsigned,grn_ctx_send(grn_ctx,*ctx,,char,*str,,unsigned,int,str_len,,int,flags);
    :DESCRIPTION
    ,,͓͘Δ
    ==,grn_ctx_recv
    :NAME
    ,,grn_ctx_recv,I,͏͚ͱΔ
    :SYNOPSIS
    ,((','))
    ,,#include,
    ,,unsigned,grn_ctx_recv(grn_ctx,*ctx,,char,**str,,unsigned,int,*str_len,,int,*flags);
    :DESCRIPTION
    ,,͏͚ͱΔ
    =,DB,API
    ==,grn_db_create
    :NAME
    ,,grn_db_create,,grn_db_open,I,σʔλϕʔεΛੜ੒͢Δ
    IUUQTHJUIVCDPNHSPPOHBHSPPOHBCMPCNBTUFSEPD"1*SE

    View full-size slide

  33. package main
    !
    /*
    #cgo pkg-config: groonga
    #include
    #include
    */
    import "C"
    import "unsafe"
    import "log"
    !
    func main() {
    C.grn_init() // TODO error handling
    defer C.grn_fin() // TODO error handling
    !
    ctx := C.grn_ctx_open(0)
    defer C.grn_ctx_fin(ctx) // TODO error handling
    !
    dbPath := "db"
    cDbPath := C.CString(dbPath)
    defer C.free(unsafe.Pointer(cDbPath))
    db := C.grn_db_create(ctx, cDbPath, nil)
    if db == nil {
    log.Fatal("[grn_db_create] Failed to create DB")
    }
    defer C.grn_obj_close(ctx, db)
    !
    command := "status"
    cCommand := C.CString(command)
    defer C.free(unsafe.Pointer(cCommand))
    C.grn_ctx_send(ctx, cCommand, C.uint(len(command)), 0) // TODO error handling
    !
    var resultBuffer *C.char
    var resultLength C.uint
    var flags C.int
    C.grn_ctx_recv(ctx, &resultBuffer, &resultLength, &flags) // TODO error handling
    result := C.GoBytes(unsafe.Pointer(resultBuffer), C.int(resultLength))
    !
    log.Println(string(result))
    }

    View full-size slide

  34. $ go run main.go
    2014/03/28 15:34:38 {"alloc_count":
    156,"starttime":1395988478,"uptime":
    0,"version":"4.0.0","n_queries":
    0,"cache_hit_rate":0.0,"command_version":
    1,"default_command_version":
    1,"max_command_version":2}

    View full-size slide

  35. ͜Θ͘ͳ͍
    w ࢝·ΓͱऴΘΓ

    HSO@JOJU
    HSO@pO

    w ίϯςΩετ HSO@DUY
    ͷ࡞੒ͱഁغ

    HSO@DUY@JOJU
    HSO@DUY@pO

    w σʔλϕʔεͷ࡞੒ɾΦʔϓϯͱΫϩʔζ

    HSO@EC@DSFBUF
    HSO@EC@PQFO
    HSO@PCK@DMPTF

    w ίϚϯυͷૹ৴ͱड৴

    HSO@DUY@TFOE
    HSO@DUY@SFDW

    View full-size slide

  36. Τϥʔॲཧʹ͍ͭͯ
    ͢͜͠

    View full-size slide

  37. IUUQHSPPOHBPSHKBEPDTSFGFSFODFBQJHSO@DUYIUNM

    View full-size slide

  38. ;ͨͭͷΤϥʔ
    w ݺͼग़ͨ͠HSO@͕໭Γ஋ͰΤϥʔΛڭ͑ͯ͘ΕΔ
    ৔߹
    w ݺͼग़͠͸੒ޭͨ͠΋ͷͷɺ࣮ߦʹ͸ࣦഊͯ͠ίϯ
    ςΩετʹΤϥʔ͕ೖΔ৔߹

    View full-size slide

  39. 39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    ==,grn_ctx_init
    :NAME
    ,,grn_ctx_init,,grn_ctx_fin,I,grn_ctxߏ଄ମΛॳظԽ/ղ์͢Δ
    :SYNOPSIS
    ,((','))
    ,,#include,
    ,,grn_rc,grn_ctx_init(grn_ctx,*ctx,,int,flags,,grn_encoding,encoding);
    ,,grn_rc,grn_ctx_fin(grn_ctx,*ctx);
    :DESCRIPTION
    ,,grn_ctx͸ɺ1)Τϥʔ৘ใͷ௨஌ɺ2)API಺෦Ͱ࢖༻͢ΔϝϞϦͷ؅ཧɺ3)ΫΤϦݴޠॲཧܥͷ؅ཧͷͨΊʹ࢖༻͞ΕΔߏ଄ମͰ͋Δɻ΄ͱΜͲͷAPIؔ਺͸ୈҰҾ਺ʹgrn_ct
    ,,,typedef,struct,_grn_ctx,grn_ctx;
    ,,,struct,_grn_ctx,{
    ,,,,,grn_rc,rc;,,,,,,,,,,,,,,,,,,,,,,,/*,࠷ޙʹ࣮ߦͨ͠APIͷऴྃίʔυ,*/
    ,,,,,int,flags;,,,,,,,,,,,,,,,,,,,,,,,/*,಺෦ॲཧ༻,*/
    ,,,,,grn_encoding,encoding;,,,,,,,,,,,/*,σϑΥϧτͷจࣈΤϯίʔσΟϯά,*/
    ,,,,,unsigned,char,ntrace;,,,,,,,,,,,,/*,όοΫτϨʔεͷ਺,*/
    ,,,,,unsigned,char,errlvl;,,,,,,,,,,,,/*,࠷ޙʹൃੜͨ͠ΤϥʔͷϨϕϧ,*/
    ,,,,,unsigned,char,stat;,,,,,,,,,,,,,,/*,಺෦ॲཧ༻,*/
    ,,,,,unsigned,int,seqno;,,,,,,,,,,,,,,/*,಺෦ॲཧ༻,*/
    ,,,,,unsigned,int,subno;,,,,,,,,,,,,,,/*,಺෦ॲཧ༻,*/
    ,,,,,unsigned,int,seqno2;,,,,,,,,,,,,,/*,಺෦ॲཧ༻,*/
    ,,,,,unsigned,int,errline;,,,,,,,,,,,,/*,Τϥʔ͕ൃੜͨ͠Օॴͷߦ൪߸,*/
    ,,,,,grn_ctx,*prev;,,,,,,,,,,,,,,,,,,,/*,಺෦ॲཧ༻,*/
    ,,,,,grn_ctx,*next;,,,,,,,,,,,,,,,,,,,/*,಺෦ॲཧ༻,*/
    ,,,,,const,char,*errfile;,,,,,,,,,,,,,/*,Τϥʔ͕ൃੜͨ͠ιʔεϑΝΠϧ໊,*/
    ,,,,,const,char,*errfunc;,,,,,,,,,,,,,/*,Τϥʔ͕ൃੜͨؔ͠਺໊,*/
    ,,,,,struct,_grn_ctx_impl,*impl;,,,,,,/*,಺෦ॲཧ༻,*/
    ,,,,,void,*trace[16];,,,,,,,,,,,,,,,,,/*,όοΫτϨʔεϙΠϯλ഑ྻ,*/
    ,,,,,char,errbuf[GRN_CTX_MSGSIZE];,,,,/*,࠷ޙʹൃੜͨ͠Τϥʔʹؔ͢Δϝοηʔδ,*/
    ,,,};
    ,,grn_ctxߏ଄ମ͸APIͰ࢖༻͢Δલʹgrn_ctx_init()ͰॳظԽ͠ͳ͚Ε͹ͳΒͳ͍ɻॳظԽ͢Δgrn_ctxߏ଄ମ΁ͷϙΠϯλΛ'ctx'ʹࢦఆ͢Δɻ'flags'ʹGRN_CTX_USE_QL
    IUUQTHJUIVCDPNHSPPOHBHSPPOHBCMPCNBTUFSEPD"1*SE

    View full-size slide

  40. package main
    !
    /*
    #cgo pkg-config: groonga
    #include
    #include
    */
    import "C"
    import "unsafe"
    import "log"
    !
    func main() {
    C.grn_init() // TODO error handling
    defer C.grn_fin() // TODO error handling
    !
    ctx := C.grn_ctx_open(0)
    defer C.grn_ctx_fin(ctx) // TODO error handling
    !
    dbPath := "db"
    cDbPath := C.CString(dbPath)
    defer C.free(unsafe.Pointer(cDbPath))
    db := C.grn_db_create(ctx, cDbPath, nil)
    if db == nil {
    log.Fatal("[grn_db_create] Failed to create DB")
    }
    defer C.grn_obj_close(ctx, db)
    !
    command := "status"
    cCommand := C.CString(command)
    defer C.free(unsafe.Pointer(cCommand))
    C.grn_ctx_send(ctx, cCommand, C.uint(len(command)), 0) // TODO error handling
    !
    var resultBuffer *C.char
    var resultLength C.uint
    var flags C.int
    C.grn_ctx_recv(ctx, &resultBuffer, &resultLength, &flags) // TODO error handling
    result := C.GoBytes(unsafe.Pointer(resultBuffer), C.int(resultLength))
    !
    log.Println(string(result))
    }
    ݺͼग़ͨ͠HSO@͕໭Γ஋Ͱ

    ΤϥʔΛڭ͑ͯ͘ΕΔ৔߹

    ࣮͸DUYSD΋(3/@46$$&44ʹͳ͍ͬͯΔ

    View full-size slide

  41. package main
    !
    /*
    #cgo pkg-config: groonga
    #include
    #include
    */
    import "C"
    import "unsafe"
    import "log"
    !
    func main() {
    C.grn_init() // TODO error handling
    defer C.grn_fin() // TODO error handling
    !
    ctx := C.grn_ctx_open(0)
    defer C.grn_ctx_fin(ctx) // TODO error handling
    !
    dbPath := "db"
    cDbPath := C.CString(dbPath)
    defer C.free(unsafe.Pointer(cDbPath))
    db := C.grn_db_create(ctx, cDbPath, nil)
    if db == nil {
    log.Fatal("[grn_db_create] Failed to create DB")
    }
    defer C.grn_obj_close(ctx, db)
    !
    command := "status"
    cCommand := C.CString(command)
    defer C.free(unsafe.Pointer(cCommand))
    C.grn_ctx_send(ctx, cCommand, C.uint(len(command)), 0) // TODO error handling
    !
    var resultBuffer *C.char
    var resultLength C.uint
    var flags C.int
    C.grn_ctx_recv(ctx, &resultBuffer, &resultLength, &flags) // TODO error handling
    result := C.GoBytes(unsafe.Pointer(resultBuffer), C.int(resultLength))
    !
    log.Println(string(result))
    }
    HUY@DUY@TFOEʹண໨

    View full-size slide

  42. ݺͼग़ͨ͠HSO@͕໭Γ஋Ͱ

    ΤϥʔΛڭ͑ͯ͘ΕΔ৔߹
    /* ུ */
    !
    command := "statussssss"
    cCommand := C.CString(command)
    defer C.free(unsafe.Pointer(cCommand))
    rc := C.grn_ctx_send(ctx, cCommand, C.uint(len(command)), 0)
    if rc != C.GRN_SUCCESS {
    log.Fatal("[grn_ctx_send(rc)]")
    }
    if ctx.rc != C.GRN_SUCCESS {
    message := C.GoString(&ctx.errbuf[0])
    log.Fatal("[grn_ctx_send(ctx.rc)] ", message)
    }
    !
    /* ུ */
    ݺͼग़͠͸੒ޭͨ͠΋ͷͷɺ

    ࣮ߦʹ͸ࣦഊͯ͠ίϯςΩετʹΤϥʔ͕ೖΔ৔߹
    UZQPͨ͠

    View full-size slide

  43. $ go run main.go
    2014/03/29 13:07:45 [grn_ctx_send(ctx.rc)]
    invalid command name: statussssss
    exit status 1

    View full-size slide

  44. l͜Μ͝ͷ͔͍ͩz

    View full-size slide

  45. ϥΠϒϥϦͱͯ͠੔͑Δ
    w %#ΛͻΒ͘৔߹ɺͭ͘Δ৔߹ͷ྆ํʹରԠ
    w (PSPVUJOFͱεϨουͱHSO@DUYΛ஥ྑ͘
    w Τϥʔͷॲཧ
    w ࣗಈԽςετ
    w ೖग़ྗΛ(PͰѻ͍қ͍ܗࣜʹ

    View full-size slide

  46. ·ͱΊ
    w (PͰ(SPPOHBCJOEJOHΛͭ͘ΔͨΊͷ

    ୈҰาΛ঺հͨ͠
    w (SPPOHBCJOEJOHͱͯ͠࢖͑Δ΋ͷʹ͢ΔͨΊʹ
    ඞཁͳ࡞ۀΛࣔͨ͠

    View full-size slide