AWS EC2 - Golang 세팅

Info/AWS 2023. 3. 15. 23:13 |
728x90

※ 해당 글은 작성자 참고용으로 작성된 글입니다.

 

※ 인스턴스 생성 후 가능합니다.

https://lazeturtle.tistory.com/34

 

AWS EC2 - 인스턴스 생성 및 Putty 연결

※ 해당 글은 작성자 참고용으로 작성된 글입니다. 1. 인스턴스 구축 대시보드 - '인스턴스 시작' 버튼 선택 이름 : 인스턴스 이름(프로젝트명) OS : Linux 키 페어 : IAM을 통해 미리 등록한 사용자 키

lazeturtle.tistory.com

※ VS Code를 연동 후 하는 것을 추천드립니다.

https://lazeturtle.tistory.com/36

 

AWS & VS Code 연동

※ 해당 글은 작성자 참고용으로 작성된 글 입니다. 인스턴스 생성 후 진행 가능 https://lazeturtle.tistory.com/34 AWS EC2 - 인스턴스 생성 및 Putty 연결 ※ 해당 글은 작성자 참고용으로 작성된 글입니다.

lazeturtle.tistory.com


1. EC2 내 Golang 기본 세팅

1) root 계정으로 변경

sudo -s

2) 업데이트

yum update -y

3) Golang 설치

sudo yum install -y golang

4) go 환경 변수 설정

export GOROOT=/usr/lib/golang
export GOPATH=$HOME/(작업 공간)
export PATH=$PATH:$GOROOT/bin

(환경변수 지정 전에 작업 공간에 대한 폴더를 미리 만들어 두세요)

(Linux 폴더 생성 명령어 : mkdir (폴더명))

 

5) go 버전 확인

go version

위 이미지처럼 나온다면 설치 성공

 

2. Golang 테스트

1) main.go 파일 생성

(별도 디렉토리에서 생성하는 것을 추천드려요 - 디렉토리 생성 명령어 : mkdir (디렉토리명))

(파일 및 디렉토리 생성시, root 권한으로 할 경우, 나중에 번거롭습니다.)

touch main.go

 

2) AWS 연동된 VS Code에서 main.go 열기 및 코드 작성

package main

import (
	"fmt"
	"log"
	"net/http"
)

func HomeEndpoint(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "Hello world & Hello lazeturtle :)")
}

func main() {
	http.HandleFunc("/", HomeEndpoint)
	if err := http.ListenAndServe(":3000", nil); err != nil {
		log.Fatal(err)
	}
}

 

3) main.go 파일 실행

go run main.go

 

4) 페이지 테스트

URL : (EC2 인스턴스 퍼블릭 IPv4 DNS):3000


실행이 안될 경우,

원인 1. URL에 포트 번호 미입력

URL에 퍼블릭 IPv4 DNS 만 입력 하고 뒤에 :3000 (Port)를 입력하지 않을 경우,

페이지가 보여지지 않을 수 있음

 

원인 2. 인바운드 규칙을 설정하지 않은 경우,

해당 코드는 Port(:3000) 에 대한 페이지를 보여주는데, 인바운드 규칙에 그런 부분이 없을 경우,

페이지가 보여지지 않을 수 있음

그렇기에 인바운드 규칙을 별도로 추가해야만 함!

 

728x90

'Info > AWS' 카테고리의 다른 글

AWS & VS Code 연동  (0) 2023.03.15
AWS EC2 - 인스턴스 생성 및 Putty 연결  (0) 2023.03.15
AWS RDS - MySQL 구축  (0) 2023.03.15
Posted by 게으른거북
:
728x90

참고 페이지 : #삽질 없는 개발은 없다

참고 페이지 : #Angular

 

Input Form에 대한 검증하는 기능을 추가하겠습니다.

총 3개의 Input이 있는데, 입력 값에 따라 Issue를 보여줄 수 있도록 합니다.

Web 실행화면

 

더보기

src/app/app.module.ts 수정

작업에 앞서서 먼저 Module를 추가해줍니다.

...
import { FormsModule, ReactiveFormsModule } from '@angular/forms';  // 코드 수정
...

const appRoutes : Routes = [
  ...
]

@NgModule({
  declarations: [
    ...
  ],
  imports: [
    ...
    ReactiveFormsModule,  // 코드 추가
    ...
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {
  ...
}

 

src/app/user/user.component.ts 수정

...
import { FormGroup, FormBuilder, Validators } from '@angular/forms';  // 코드 수정
...

@Component({
  ...
})
export class UserComponent implements OnInit {

  ...

  complexForm : FormGroup;	// 코드 추가

  constructor(
    public service: UserService,
    private toastr: ToastrService,
    private fbuilder : FormBuilder  // 코드 추가
  ) {
      this.service.getUsers()
      .subscribe((data) => {
        ...
      })

    this.service.selectedUser = {
      ...
    };
    
    // 코드 추가
    // 필드 당 여러개의 유효성 검사기 추가. 
    // 두개 이상 검사하려면 Validators.complose 함수로 검사 항목을 맵핑해야함
    this.complexForm = fbuilder.group({
      "name": [
        null, 
        Validators.compose([
          Validators.required,		// 입력 여부 체크
          Validators.minLength(2),	// 최소 글자수 2개
          Validators.maxLength(20),	// 최대 글자수 20개
          Validators.pattern('[ㄱ-ㅎ|가-힣|a-z|A-Z|0-9|\*]+$')	// 한글, 영문(대소문자), 숫자 포함 여부 체크
        ])
      ],
      "email": [
        null, 
        Validators.compose([
          Validators.required,		// 입력 여부 체크
          Validators.email			// 이메일 형식 체크
        ])
      ],
      "password": [
        null, 
        Validators.compose([
          Validators.required,		// 입력 여부 체크
          // 영문(대소문자), 숫자, 특수문자가 각각 1개 이상 포함하여야 하며, 6글자 이상 입력 여부 체크
          Validators.pattern('(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[!@#$%^*+=-]).{6,}$')
        ])
      ]
    })
  }

  ngOnInit(): void {
  }
  
  ...
}

 

Validators 함수 (링크)

class Validators {
  static min(min: number): ValidatorFn
  static max(max: number): ValidatorFn
  static required(control: AbstractControl): ValidationErrors | null
  static requiredTrue(control: AbstractControl): ValidationErrors | null
  static email(control: AbstractControl): ValidationErrors | null
  static minLength(minLength: number): ValidatorFn
  static maxLength(maxLength: number): ValidatorFn
  static pattern(pattern: string | RegExp): ValidatorFn
  static nullValidator(control: AbstractControl): ValidationErrors | null
  static compose(validators: ValidatorFn[]): ValidatorFn | null
  static composeAsync(validators: AsyncValidatorFn[]): AsyncValidatorFn | null
}

 

 

src/app/user/user.component.html 수정

<div class="container">
  <header>
    ...
  </header>

  <hr>

  <div class="row">
    <div class="col-md-12">
      <h3>Insert User Data</h3>
      <!-- 코드 수정 -->
      <form method="post" #form="ngForm" [formGroup]="complexForm"  (ngSubmit)="onSubmit(form)">
        <input type="hidden" name="id" [(ngModel)]="service.selectedUser.id">
        <div class="form-group">
          <label for="name">Name : </label>
          <!-- 코드 수정 -->
          <input type="text" name="name" id="name" class="form-control" placeholder="insert your name"
            [(ngModel)]="service.selectedUser.name" [formControl]="complexForm.controls['name']">
          <!-- 코드 추가 -->
          <div *ngIf="complexForm.controls['name'].touched && !complexForm.controls['name'].valid" class="alert alert-danger">

            <div *ngIf="complexForm.controls['name'].hasError('required')" >필수 입력사항입니다.</div>

            <div *ngIf="complexForm.controls['name'].hasError('pattern')" >특수문자 및 숫자를 입력하실 수 없습니다.</div>

            <div *ngIf="complexForm.controls['name'].hasError('minlength') || complexForm.controls['name'].hasError('maxlength')" >2~20자 이내로 입력해주세요.</div>

          </div>
        </div>
        <div class="form-group">
          <label for="email">Email : </label>
          <!-- 코드 수정 -->
          <input type="text" name="email" id="email" class="form-control" placeholder="insert your email"
            [(ngModel)]="service.selectedUser.email" [formControl]="complexForm.controls['email']">
          <!-- 코드 추가 -->
          <div *ngIf="complexForm.controls['email'].touched && !complexForm.controls['email'].valid" class="alert alert-danger">
            
            <div *ngIf="complexForm.controls['email'].hasError('required')" >필수 입력사항입니다.</div>

            <div *ngIf="complexForm.controls['email'].hasError('email')" >이메일 형식으로 입력해 주세요.</div>

          </div>

        </div>
        <div class="form-group">
          <label for="password">Password : </label>
          <!-- 코드 수정 -->
          <input type="text" name="password" id="password" class="form-control" placeholder="insert your password"
            [(ngModel)]="service.selectedUser.password" [formControl]="complexForm.controls['password']">
          <!-- 코드 추가 -->
          <div *ngIf="complexForm.controls['password'].touched && !complexForm.controls['password'].valid" class="alert alert-danger">
            
            <div *ngIf="complexForm.controls['password'].hasError('required')" >필수 입력사항입니다.</div>

            <div *ngIf="complexForm.controls['password'].hasError('pattern')" >영문(대소문자), 숫자, 특수문자(!@#$%^*+=-)를 조합하여 8자리 이상 입력해주세요.</div>

          </div>

        </div>

        <div class="form-row">
          <div class="d-grid gap-2 d-md-flex justify-content-md-end">
          	<!-- 코드 수정 -->
            <button class="btn btn-sm btn-block btn-primary col-lg-2" [disabled]="!complexForm.valid">
              submit &nbsp; <fa-icon icon="user-plus"></fa-icon>
            </button>

            <button class="btn btn-sm btn-block btn-secondary col-lg-2" (click)="clearForm()">
              clear &nbsp; <fa-icon icon="undo"></fa-icon>
            </button>
          </div>
        </div>
      </form>
    </div>
  </div>

  <div class="row">
    ...
  </div>


  <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
    ...
  </div>

  <br>
  <footer>
    ...
  </footer>
</div>

 

실행화면

Web 실행화면 - 초기화면

초기 실행화면에서는 입력값에 대해 Required Error가 발생되었있기에,

submit 버튼이 비활성화 상태로 되어있습니다.

 

Web 실행화면 - 에러화면

입력폼을 가볍게(?) 터치하고 넘어가면, Required Error로 인해,

문구가 표시되는 것을 볼 수 있습니다.

 

Web 실행화면 - 에러화면

각각의 입력폼에 대한 Error로 표시되는 문구가 다르게 표시되는 이유는,

user.component.html에서 <div> 태그 내 *ngIf를 다르게 지정했기 때문입니다.

 

Web 실행화면 - 성공 화면

입력에 대한 검증에 맞추어 잘 입력해주시면,

Issue 문구도 사라지고, submit 버튼도 활성화 되어집니다.

 

728x90
Posted by 게으른거북
:
728x90

참고페이지 : 구글링 검색을 통해 습득하여 적용

 

기존에 작업하던 app.component에서

새로 생성할 user.component로 코드를 이동하였습니다.

 

페이지를 이원화 하여, Router 연결 작업을 진행하였습니다.

 

더보기

Component 추가

프로젝트 폴더로 이동하여 Component 추가합니다.

cd workspace/angular/myApp
ng generate component user
cmd 결과 화면 - Component 생성

src/app/app.component.html 초기화

기존의 코드로 초기화 하여 새로 생성될 user의 Component와 충돌되지 않도록 합니다.

<div class="mat-app-background">
  <div class="mat-elevation-z4">
    
  </div>
  <!-- 라우터에 연결된 Component 표시해 줍니다. -->
  <router-outlet></router-outlet>
</div>

 

src/app/app.components.ts 초기화

기존의 코드로 초기화 하여 새로 생성될 user의 Component와 충돌되지 않도록 합니다.

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'myApp';
 
  constructor() {  }
  
  ngOnInit(): void {
  }
}

 

src/app/app.module.ts 수정

Router와 관련된 모듈을 Import 해 줍니다.

...

// Router 추가
import { Routes, RouterModule } from '@angular/router';

// URI를 위한 라우터값과 Component를 지정합니다.
const appRoutes : Routes = [
  { path: '', component: AppComponent }, 
  { path: 'user', component: UserComponent }	
]

@NgModule({
  declarations: [
    AppComponent,
    // user component를 생성할 경우 자동으로 생성되느 코드
    UserComponent
  ],
  imports: [
    ...
    
    // 코드 추가
    RouterModule.forRoot(appRoutes)
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {
  ...
}

 

src/app/user/user.component.ts 수정

app.component.ts에 있는 코드를 가져온 후 수정합니다.

import { Component, OnInit } from '@angular/core';

import { UserService } from './../user.service';
import { FormGroup } from '@angular/forms';
import { ToastrService } from 'ngx-toastr';

@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit {

  title = 'myApp';
   
  users: Array<any> = [];

  userId = null;  
  displayForm : boolean = false;  

  constructor(
    public service: UserService,
    private toastr: ToastrService
  ) {
    this.service.getUsers()
      .subscribe((data) => {
        this.users = data;
        console.log(this.users);
        this.onForm();
      })

    this.service.selectedUser = {
      "id": null,
      "name": '',
      "email": '',
      "password": ''
    };
  }

  ngOnInit(): void {
  }

  // toastr을 간편하게 쓰기 위한 함수
  public onToastr(service: string, title: string, message: string) {
    switch(service) {
      case "success": {
        this.toastr.success(message, title, {timeOut: 2000});
        break;
      }
      case "info": {
        this.toastr.info(message, title, {timeOut: 2000});
        break;
      }
      case "warning": {
        this.toastr.warning(message, title, {timeOut: 2000});
        break;
      }
      case "error": {
        this.toastr.error(message, title, {timeOut: 2000});
        break;
      }
      default: {
        console.log("Toast Error");
        break;
      }
    }
  }

  public onForm() {
    
    if(this.users.length > 0) {
      this.displayForm = true;
      return;
    }

    this.displayForm = false;
  }

  public onSubmit(form: FormGroup) {
 
    console.log(form.value)

    if( form.value.id == null) {
      console.log(form.value.name)

      this.service.postUser(form.value)
        .subscribe((resp) => {
          console.log(resp)

          if(resp["Status"] == 201) {
            this.clearForm();   

            this.service.getUsers()
              .subscribe((data) => {
                // 코드 추가
                this.onToastr("success", "Data Insert", "새로운 User가 등록되었습니다.");

                this.users = data
                this.onForm();

                this.service.nextUserId = (data[ data.length -1].id +1);
                console.log("ID disponivel : " + this.service.nextUserId);
              });
          }
        });
    } else {
      
      this.service.putUser(form.value)
        .subscribe((resp) => {
          console.log(resp);

          if(resp["Status"] == 200) {
            // 코드 추가
            this.onToastr("info", "Data Edit", "User 정보가 수정되었습니다.");

            this.onForm();
            this.clearForm();
            this.updateList(form.value);
          }
        });

        
    }
  }

  public onEdit(id: string) {

    this.service.getUser(id)
      .subscribe((data) => {
        this.service.selectedUser = data;
      });
  }

  public updateList(user: any) {
    for(var i = 0; i < this.users.length; i++) {
      if(user.id == this.users[i].id) {
        this.users[i] = user;
        return;
      }
    }
  }

  public deleteConfirm(id: string) {
    this.userId = id;
  }

  public cancelDelete() {
    this.userId = null;
    console.log("Cancel User Delete");
  }

  public onDelete() { 

    if(this.userId != null) {
      this.service.deleteUser(this.userId)
        .subscribe((resp) => {
          console.log(resp);
  
          if(resp["Status"] == 200) {
            // 코드 추가
            this.onToastr("error", "Data Delete", "User 정보가 삭제되었습니다.");

            this.service.nextUserId = (this.users[ this.users.length -1].id +1);
            console.log("ID disponivel : " + this.service.nextUserId);

            this.users = this.users.filter((user) => user.id != this.userId);

            this.cancelDelete();
            this.onForm();
          }
        });
    }
  }

  public clearForm() {
    this.service.selectedUser = {
      "id": null,
      "name": '',
      "email": '',
      "password": ''
    };
  }

}

 

src/app/user/user.component.html 수정

<div class="container">
  <header>
    <nav>
      <ul class="nav justify-content-end">
        <li class="nav-item">
          <a class="nav-link active" aria-current="page" href="#">Home</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#">User</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#">Contact</a>
        </li>
      </ul>
    </nav>
  </header>

  <hr>

  <div class="row">
    <div class="col-md-12">
      <h3>Insert User Data</h3>
      <form method="post" #form="ngForm" (ngSubmit)="onSubmit(form)">

        <input type="hidden" name="id" [(ngModel)]="service.selectedUser.id">
        <div class="form-group">
          <label for="name">Name : </label>
          <input type="text" name="name" id="name" class="form-control" placeholder="insert your name"
            [(ngModel)]="service.selectedUser.name" required>
        </div>
        <div class="form-group">
          <label for="email">Email : </label>
          <input type="text" name="email" id="email" class="form-control" placeholder="insert your email"
            [(ngModel)]="service.selectedUser.email" required>
        </div>
        <div class="form-group">
          <label for="password">Password : </label>
          <input type="text" name="password" id="password" class="form-control" placeholder="insert your password"
            [(ngModel)]="service.selectedUser.password" required>
        </div>

        <div class="form-row">
          <div class="d-grid gap-2 d-md-flex justify-content-md-end">
            <button class="btn btn-sm btn-block btn-primary col-lg-2" [disabled]="!form.valid">
              submit &nbsp; <fa-icon icon="user-plus"></fa-icon>
            </button>

            <button class="btn btn-sm btn-block btn-secondary col-lg-2" (click)="clearForm()">
              clear &nbsp; <fa-icon icon="undo"></fa-icon>
            </button>
          </div>
        </div>
      </form>
    </div>
  </div>

  <div class="row">
    <div clas="col-md-12" *ngIf="!displayForm">
      <p class="alert alert-warning text-center" >
        호출 가능한 User 데이터가 없습니다. <br>
        새로운 User 를 등록해주세요.
      </p>
    </div>

    <div clas="col-md-12" *ngIf="displayForm">

      <h3>User Data List</h3>

      <table class="table table-bordered table-hover text-center">
        <thead>
          <tr>
            <th>Id</th>
            <th>Name</th>
            <th>Email</th>
            <th>Password</th>
            <th>Edit</th>
            <th>Delete</th>
          </tr>
        </thead>
        <tbody>
          <tr *ngFor="let user of users">
            <td>{{ user.id }}</td>
            <td>{{ user.name }}</td>
            <td>{{ user.email }}</td>
            <td>{{ user.password }}</td>
            <td>
              <button type="button" class="btn btn-sm btn-info col-block col-lg-8" (click)="onEdit(user.id)">
                <fa-icon icon="edit"></fa-icon>
              </button>
            </td>
            <td>
              <button type="button" class="btn btn-sm btn-danger col-block col-lg-8" (click)="onDelete(user.id)" data-bs-toggle="modal" data-bs-target="#exampleModal" (click)="deleteConfirm(user.id)">
                <fa-icon icon="user-minus"></fa-icon>
              </button>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>


  <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="exampleModalLabel">User Data Delete</h5>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" (click)="cancelDelete()"></button>
        </div>
        <div class="modal-body">
          회원 <strong class="text-danger"> #{{ userId }} </strong> 번의  정보를 삭제 하시겠습니까?
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-bs-dismiss="modal" (click)="cancelDelete()">
            Cancle
          </button>

          <button type="button" class="btn btn-danger" data-bs-dismiss="modal" (click)="onDelete()">
            Delete
          </button>
        </div>
      </div>
    </div>
  </div>

  <br>
  <footer>
    <p class="alert text-center"></p>
  </footer>
</div>

 

결과화면

Web 결과화면 - app.component.html

위 이미지와 같이 localhost:4200 으로 접속하면,
빈 화면이 표시됩니다.

 

Web 결과화면 - user/user.component.html

위에서 지정했었던 Router 값을 URL(localhost:4200/user)로 접속하면,

미리 작업해 두었던 화면이 표시됩니다.

 

<a> 태그를 활용하여 페이지 이동이 가능한 것입니다.

728x90
Posted by 게으른거북
:
728x90

참고페이지 : Using Go with MariaDB (링크

 

Using Go with MariaDB | MariaDB

2019 Webinar: Building Modern Applications with MariaDB Hybrid Transactional/Analytical Processing (HTAP) Watch Now _________________________ I have been using Google’s Go programming language for a…

mariadb.com

이전 Database 연동 작업 이후,

생성(Create-POST), 읽기(Read-GET), 수정(Update-PUT), 삭제(Delete-DELETE)

작업을 추가로 진행하겠습니다.

 

더보기

main.go 수정

...

func main() {
	...
}

func connetDatabase() *sql.DB { ... }

func checkErr(err error) { ... }

func getUsers(w http.ResponseWriter, r *http.Request) { ... }

// 특정 user 정보 전달
func getUser(w http.ResponseWriter, r *http.Request) {
	setJsonHeader(w)
	HttpInfo(r)

	// 파라미터값 체크
	params := mux.Vars(r)

	// 파라미터값 중 id값 추출
	id, _ := strconv.Atoi(params["id"])

	// 주석 처리 or 제거
	// 일치하는 user id를 확인
	/*for _, user := range users {
		if user.Id == id {
			// 일치하는 user의 데이터 표시 및 함수 종료
			json.NewEncoder(w).Encode(user)
			return
		}
	}*/

	// 코드 추가
	// sql.DB 객체 생성
	db := connetDatabase()

	// 지연하여 닫는다(필수)
	defer db.Close()

	// 하나의 Row를 갖는 SQL 쿼리
	user = User{}

	err := db.QueryRow("SELECT * FROM users WHERE id = ?", id).Scan(&user.Id, &user.Name, &user.Email, &user.Password)
	checkErr(err)
	fmt.Println(user)

	if user.Id != 0 {
		// 일치하는 user의 데이터 표시 및 함수 종료
		json.NewEncoder(w).Encode(user)
		return
	} else {
		json.NewEncoder(w).Encode(NewResponse(r.Method, "failed", 400))
	}
}

// user 정보 추가
func postUser(w http.ResponseWriter, r *http.Request) {
	setJsonHeader(w)
	HttpInfo(r)

	body, _ := ioutil.ReadAll(r.Body)

	var user User
	err := json.Unmarshal(body, &user)
	defer r.Body.Close()

	if err != nil {
		json.NewEncoder(w).Encode(NewResponse(r.Method, "failed", 400))
		return
	}

	// 주석 처리 or 제거
	//users = append(users, user)

	// 코드 추가
	// sql.DB 객체 생성
	db := connetDatabase()
	defer db.Close()

	// INSERT 문 실행
	result, err := db.Exec("INSERT INTO users VALUES (?, ?, ?, ?)", user.Id, user.Name, user.Email, user.Password)
	checkErr(err)

	// sql.Result.RowsAffected() 체크
	n, err := result.RowsAffected()
	if n == 1 {
		fmt.Println("1 row inserted.")
	} else {
		json.NewEncoder(w).Encode(NewResponse(r.Method, "failed", 400))
		return
	}

	json.NewEncoder(w).Encode(NewResponse(r.Method, "success", 201))
}

// user 정보 수정
func putUser(w http.ResponseWriter, r *http.Request) {
	setJsonHeader(w)
	HttpInfo(r)

	params := mux.Vars(r)

	id, _ := strconv.Atoi(params["id"])

	body, _ := ioutil.ReadAll(r.Body)

	var user User

	err := json.Unmarshal(body, &user)

	checkErr(err)

	// 주석 처리 or 제거
	/*for index, _ := range users {
		if users[index].Id == id {
			users[index] = user

			json.NewEncoder(w).Encode(NewResponse(r.Method, "success", 200))
			return
		}
	}

	json.NewEncoder(w).Encode(NewResponse(r.Method, "failed", 400))*/

	// 코드 추가
	// sql.DB 객체 생성
	db := connetDatabase()
	defer db.Close()

	// UPDATE 문 실행
	result, err := db.Exec("UPDATE users SET id=?, name=?, email=?, password=? WHERE id=?", user.Id, user.Name, user.Email, user.Password, id)
	checkErr(err)

	// sql.Result.RowsAffected() 체크
	n, err := result.RowsAffected()
	if n == 1 {
		fmt.Println("1 row updated.")
	} else {
		json.NewEncoder(w).Encode(NewResponse(r.Method, "failed", 400))
		return
	}

	json.NewEncoder(w).Encode(NewResponse(r.Method, "success", 201))
}

// user 정보 삭제
func deleteUser(w http.ResponseWriter, r *http.Request) {

	setJsonHeader(w)

	HttpInfo(r)

	params := mux.Vars(r)

	id, _ := strconv.Atoi(params["id"])

	// 주석 처리 or 제거
	/*for index, _ := range users {
		if users[index].Id == id {
			users = append(users[:index], users[index+1:]...)

			json.NewEncoder(w).Encode(NewResponse(r.Method, "success", 200))

			return
		}
	}

	json.NewEncoder(w).Encode(NewResponse(r.Method, "failed", 400))*/

	// 코드 추가
	// sql.DB 객체 생성
	db := connetDatabase()
	defer db.Close()

	// Delete 문 실행
	result, err := db.Exec("DELETE FROM users WHERE id = ?", id)
	checkErr(err)

	// sql.Result.RowsAffected() 체크
	n, err := result.RowsAffected()
	if n == 1 {
		fmt.Println("1 row deleted.")
	} else {
		json.NewEncoder(w).Encode(NewResponse(r.Method, "failed", 400))
		return
	}

	json.NewEncoder(w).Encode(NewResponse(r.Method, "success", 200))
}

 

728x90
Posted by 게으른거북
:
728x90

참고페이지 : Using Go with MariaDB (링크)

 

Using Go with MariaDB | MariaDB

2019 Webinar: Building Modern Applications with MariaDB Hybrid Transactional/Analytical Processing (HTAP) Watch Now _________________________ I have been using Google’s Go programming language for a…

mariadb.com

 

MariaDB 홈페이지에서도 mysql로 작업을 환경을 구축하도록 안내하기에

혼선이 없으시길 바랍니다.

 

데이터베이스를 연동하여,

user의 전체 데이터를 가져오는 내용으로 소스를 변경하겠습니다.

 

더보기

Database 세팅

데이터베이스, 테이블을 아래 이미지와 같이 미리 생성해 주세요.

테스트를 위해 2~3개정도의 데이터를 미리 입력하는 것이 좋습니다.

MariaDB - test_crud 데이터베이스 - users 테이블

Mysql 세팅

cmd에서 프로젝트 페이지로 이동 후, 라이브러리를 다운합니다.

cd workspace/go/src/api
go get github.com/go-sql-driver/mysql

 

main.go 수정

package main

import (
	...
    
	// 코드 추가
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
)

type User struct {
	...
}

// Database 정보를 저장할 구조체
type DBInfo struct {
	user     string
	pwd      string
	url      string
	engine   string
	database string
}

// 주석 처리 or 제거
// Database에서 정보를 받아오기에, 더 이상 쓰지 않음
/*
var users = []User{
	User{Id: 1, Name: "David", Email: "test@gmail.com", Password: "123"},
	User{Id: 2, Name: "Nata", Email: "test@email.com", Password: "qwer"},
}
*/

// 코드 추가
var users = []User{} // 별도로 데이터를 저장
var user = User{}    // 별도로 데이터를 저장

// Database 연결 정보
var dbInfo = DBInfo{"아이디", "비밀번호", "localhost:3306", "mysql", "test_crud"}

type Response struct { ... }

func NewResponse(method, message string, status int) Response { ... }

func HttpInfo(r *http.Request) { ... }

// Content-Type을 "application/json"으로 설정하여 JSON 전달
func setJsonHeader(w http.ResponseWriter) {
	w.Header().Set("Content-Type", "application/json")
}

func main() { ... }

// 코드 추가 : sql.DB 객체 생성
func connetDatabase() *sql.DB {
	dataSource := dbInfo.user + ":" + dbInfo.pwd + "@tcp(" + dbInfo.url + ")/" + dbInfo.database
	db, err := sql.Open(dbInfo.engine, dataSource)

	checkErr(err)

	return db
}

// 코드 추가 : 에러 체크
func checkErr(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

// 전체 user 정보 전달
func getUsers(w http.ResponseWriter, r *http.Request) {
	setJsonHeader(w)
	HttpInfo(r)

	// sql.DB 객체 생성
	db := connetDatabase()
	
	// 지연하여 닫는다(필수)
	defer db.Close()

	// User 전체 데이터를 불러오는 SQL 쿼리
	rows, err := db.Query("SELECT * FROM users")
	checkErr(err)

	// 지연하여 닫는다(필수)
	defer rows.Close() 

	users = []User{}
	for rows.Next() {
		user = User{}
		err := rows.Scan(&user.Id, &user.Name, &user.Email, &user.Password)
		checkErr(err)
		fmt.Println(user)
		users = append(users, user)
	}

	fmt.Println(len(users))

	json.NewEncoder(w).Encode(users)
}

...
728x90
Posted by 게으른거북
: